diff --git a/Kha/Backends/Kore-HL/kha/Image.hx b/Kha/Backends/Kore-HL/kha/Image.hx index 4168f8f6..97b52855 100644 --- a/Kha/Backends/Kore-HL/kha/Image.hx +++ b/Kha/Backends/Kore-HL/kha/Image.hx @@ -142,6 +142,8 @@ class Image implements Canvas implements Resource { return 5; case A16: return 7; + case R32UI: + return 8; default: return 1; // Grey8 } diff --git a/Kha/Backends/Kore-hxcpp/kha/Image.hx b/Kha/Backends/Kore-hxcpp/kha/Image.hx index 24eab584..5eabff89 100644 --- a/Kha/Backends/Kore-hxcpp/kha/Image.hx +++ b/Kha/Backends/Kore-hxcpp/kha/Image.hx @@ -234,6 +234,8 @@ class Image implements Canvas implements Resource { return 5; case A16: return 7; + case R32UI: + return 8; default: return 1; // Grey8 } diff --git a/Kha/Backends/Krom/Krom.hx b/Kha/Backends/Krom/Krom.hx index eb0e7fd3..c189f8d5 100644 --- a/Kha/Backends/Krom/Krom.hx +++ b/Kha/Backends/Krom/Krom.hx @@ -23,6 +23,7 @@ extern class Krom { static function setRenderTarget(stage: kha.graphics4.TextureUnit, renderTarget: Dynamic): Void; static function setTextureDepth(unit: kha.graphics4.TextureUnit, texture: Dynamic): Void; static function setImageTexture(stage: kha.graphics4.TextureUnit, texture: Dynamic): Void; + static function setImageRenderTarget(stage: kha.graphics4.TextureUnit, renderTarget: Dynamic): Void; static function setTextureParameters(texunit: kha.graphics4.TextureUnit, uAddressing: Int, vAddressing: Int, minificationFilter: Int, magnificationFilter: Int, mipmapFilter: Int): Void; static function setTexture3DParameters(texunit: kha.graphics4.TextureUnit, uAddressing: Int, vAddressing: Int, wAddressing: Int, minificationFilter: Int, diff --git a/Kha/Backends/Krom/kha/Image.hx b/Kha/Backends/Krom/kha/Image.hx index 1139799b..217357e6 100644 --- a/Kha/Backends/Krom/kha/Image.hx +++ b/Kha/Backends/Krom/kha/Image.hx @@ -75,6 +75,8 @@ class Image implements Canvas implements Resource { return 5; case A16: return 7; + case R32UI: + return 8; default: return 1; // Grey8 } @@ -200,6 +202,7 @@ class Image implements Canvas implements Resource { case RGBA64: 8; case A32: 4; case A16: 2; + case R32UI: 4; default: 4; } } diff --git a/Kha/Backends/Krom/kha/compute/Compute.hx b/Kha/Backends/Krom/kha/compute/Compute.hx index e037f6f4..c450b00d 100644 --- a/Kha/Backends/Krom/kha/compute/Compute.hx +++ b/Kha/Backends/Krom/kha/compute/Compute.hx @@ -106,7 +106,7 @@ class Compute { public static function setSampledDepthTexture(unit: TextureUnit, texture: Image) { if (texture == null) return; - Krom.setSampledDepthTextureCompute(unit, texture); + Krom.setSampledDepthTextureCompute(unit, texture.renderTarget_); } public static function setSampledCubeMap(unit: TextureUnit, cubeMap: CubeMap) { @@ -118,7 +118,7 @@ class Compute { public static function setSampledDepthCubeMap(unit: TextureUnit, cubeMap: CubeMap) { if (cubeMap == null) return; - Krom.setSampledDepthTextureCompute(unit, cubeMap); + Krom.setSampledDepthTextureCompute(unit, cubeMap.renderTarget_); } public static function setTextureParameters(unit: TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing, diff --git a/Kha/Backends/Krom/kha/compute/ShaderStorageBuffer.hx b/Kha/Backends/Krom/kha/compute/ShaderStorageBuffer.hx index 61b402af..3a175da8 100644 --- a/Kha/Backends/Krom/kha/compute/ShaderStorageBuffer.hx +++ b/Kha/Backends/Krom/kha/compute/ShaderStorageBuffer.hx @@ -9,14 +9,7 @@ class ShaderStorageBuffer { public function new(indexCount: Int, type: VertexData) { myCount = indexCount; data = new Array(); - data[myCount - 1] = 0; - init(indexCount, type); - } - - function init(indexCount: Int, type: VertexData) { - myCount = indexCount; - data = new Array(); - data[myCount - 1] = 0; + if (myCount > 0) data[myCount - 1] = 0; } public function delete(): Void {} diff --git a/Kha/Backends/Krom/kha/krom/Graphics.hx b/Kha/Backends/Krom/kha/krom/Graphics.hx index 3ea614fe..ee9ba278 100644 --- a/Kha/Backends/Krom/kha/krom/Graphics.hx +++ b/Kha/Backends/Krom/kha/krom/Graphics.hx @@ -122,7 +122,12 @@ class Graphics implements kha.graphics4.Graphics { public function setImageTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void { if (texture == null) return; - Krom.setImageTexture(unit, texture.texture_); + if (texture.texture_ != null) { + Krom.setImageTexture(unit, texture.texture_); + } + else if (texture.renderTarget_ != null) { + Krom.setImageRenderTarget(unit, texture.renderTarget_); + } } public function setTextureParameters(texunit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing, diff --git a/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/OpenGL.c.h b/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/OpenGL.c.h index 47595b22..d4ff003c 100644 --- a/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/OpenGL.c.h +++ b/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/OpenGL.c.h @@ -821,8 +821,19 @@ int kinc_g4_max_bound_textures(void) { return units; } +static int getUnitStage(kinc_g4_texture_unit_t unit) { + for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) { + if (unit.stages[i] >= 0) { + return unit.stages[i]; + } + } + return -1; +} + static void setTextureAddressingInternal(GLenum target, kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) { - glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]); + int stage = getUnitStage(unit); + if (stage < 0) return; + glActiveTexture(GL_TEXTURE0 + stage); GLenum texDir; switch (dir) { case KINC_G4_TEXTURE_DIRECTION_U: @@ -841,39 +852,39 @@ static void setTextureAddressingInternal(GLenum target, kinc_g4_texture_unit_t u case KINC_G4_TEXTURE_ADDRESSING_CLAMP: glTexParameteri(target, texDir, GL_CLAMP_TO_EDGE); if (dir == KINC_G4_TEXTURE_DIRECTION_U) { - texModesU[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = GL_CLAMP_TO_EDGE; + texModesU[stage] = GL_CLAMP_TO_EDGE; } else { - texModesV[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = GL_CLAMP_TO_EDGE; + texModesV[stage] = GL_CLAMP_TO_EDGE; } break; case KINC_G4_TEXTURE_ADDRESSING_REPEAT: glTexParameteri(target, texDir, GL_REPEAT); if (dir == KINC_G4_TEXTURE_DIRECTION_U) { - texModesU[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = GL_REPEAT; + texModesU[stage] = GL_REPEAT; } else { - texModesV[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = GL_REPEAT; + texModesV[stage] = GL_REPEAT; } break; case KINC_G4_TEXTURE_ADDRESSING_BORDER: // unsupported glTexParameteri(target, texDir, GL_CLAMP_TO_EDGE); if (dir == KINC_G4_TEXTURE_DIRECTION_U) { - texModesU[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = GL_CLAMP_TO_EDGE; + texModesU[stage] = GL_CLAMP_TO_EDGE; } else { - texModesV[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = GL_CLAMP_TO_EDGE; + texModesV[stage] = GL_CLAMP_TO_EDGE; } break; case KINC_G4_TEXTURE_ADDRESSING_MIRROR: // unsupported glTexParameteri(target, texDir, GL_REPEAT); if (dir == KINC_G4_TEXTURE_DIRECTION_U) { - texModesU[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = GL_REPEAT; + texModesU[stage] = GL_REPEAT; } else { - texModesV[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = GL_REPEAT; + texModesV[stage] = GL_REPEAT; } break; } @@ -881,11 +892,15 @@ static void setTextureAddressingInternal(GLenum target, kinc_g4_texture_unit_t u } int Kinc_G4_Internal_TextureAddressingU(kinc_g4_texture_unit_t unit) { - return texModesU[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]]; + int stage = getUnitStage(unit); + if (stage < 0) return GL_CLAMP_TO_EDGE; + return texModesU[stage]; } int Kinc_G4_Internal_TextureAddressingV(kinc_g4_texture_unit_t unit) { - return texModesV[unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]]; + int stage = getUnitStage(unit); + if (stage < 0) return GL_CLAMP_TO_EDGE; + return texModesV[stage]; } void kinc_g4_set_texture_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) { @@ -899,7 +914,9 @@ void kinc_g4_set_texture3d_addressing(kinc_g4_texture_unit_t unit, kinc_g4_textu } static void setTextureMagnificationFilterInternal(GLenum target, kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) { - glActiveTexture(GL_TEXTURE0 + texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]); + int stage = getUnitStage(texunit); + if (stage < 0) return; + glActiveTexture(GL_TEXTURE0 + stage); glCheckErrors(); switch (filter) { case KINC_G4_TEXTURE_FILTER_POINT: @@ -964,26 +981,34 @@ static void setMinMipFilters(GLenum target, int unit) { } void kinc_g4_set_texture_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) { - minFilters[texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = filter; - setMinMipFilters(GL_TEXTURE_2D, texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]); + int stage = getUnitStage(texunit); + if (stage < 0) return; + minFilters[stage] = filter; + setMinMipFilters(GL_TEXTURE_2D, stage); } void kinc_g4_set_texture3d_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) { - minFilters[texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = filter; + int stage = getUnitStage(texunit); + if (stage < 0) return; + minFilters[stage] = filter; #ifndef KINC_OPENGL_ES - setMinMipFilters(GL_TEXTURE_3D, texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]); + setMinMipFilters(GL_TEXTURE_3D, stage); #endif } void kinc_g4_set_texture_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) { - mipFilters[texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = filter; - setMinMipFilters(GL_TEXTURE_2D, texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]); + int stage = getUnitStage(texunit); + if (stage < 0) return; + mipFilters[stage] = filter; + setMinMipFilters(GL_TEXTURE_2D, stage); } void kinc_g4_set_texture3d_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) { - mipFilters[texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]] = filter; + int stage = getUnitStage(texunit); + if (stage < 0) return; + mipFilters[stage] = filter; #ifndef KINC_OPENGL_ES - setMinMipFilters(GL_TEXTURE_3D, texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]); + setMinMipFilters(GL_TEXTURE_3D, stage); #endif } diff --git a/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/compute.c.h b/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/compute.c.h index 567e9bad..3a4c6479 100644 --- a/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/compute.c.h +++ b/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/compute.c.h @@ -190,6 +190,17 @@ void kinc_g4_set_compute_shader(kinc_g4_compute_shader *shader) { #endif } +void kinc_g4_set_image_render_target(kinc_g4_texture_unit_t unit, kinc_g4_render_target_t *render_target) { +#if defined(KINC_WINDOWS) || (defined(KINC_LINUX) && defined(GL_VERSION_4_4)) + for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) { + if (unit.stages[i] >= 0) { + glBindImageTexture(unit.stages[i], render_target->impl._texture, 0, GL_FALSE, 0, GL_READ_WRITE, convertInternalRTFormat((kinc_g4_render_target_format_t)render_target->impl.format)); + } + } + glCheckErrors(); +#endif +} + void kinc_g4_compute(int x, int y, int z) { #ifdef HAS_COMPUTE glDispatchCompute(x, y, z); diff --git a/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/rendertarget.c.h b/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/rendertarget.c.h index 207701e8..476a18d3 100644 --- a/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/rendertarget.c.h +++ b/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/rendertarget.c.h @@ -360,17 +360,23 @@ void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) { } void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) { - glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]); - glCheckErrors(); - glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._texture); - glCheckErrors(); + for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) { + if (unit.stages[i] >= 0) { + glActiveTexture(GL_TEXTURE0 + unit.stages[i]); + glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._texture); + glCheckErrors(); + } + } } void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) { - glActiveTexture(GL_TEXTURE0 + unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT]); - glCheckErrors(); - glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._depthTexture); - glCheckErrors(); + for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) { + if (unit.stages[i] >= 0) { + glActiveTexture(GL_TEXTURE0 + unit.stages[i]); + glBindTexture(renderTarget->isCubeMap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, renderTarget->impl._depthTexture); + glCheckErrors(); + } + } } void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) { diff --git a/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/texture.c.h b/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/texture.c.h index 539e7d3d..d849768a 100644 --- a/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/texture.c.h +++ b/Kha/Kore/Backends/Graphics4/OpenGL/Sources/kinc/backend/graphics4/texture.c.h @@ -99,6 +99,8 @@ static int convertFormat(kinc_image_format_t format) { case KINC_IMAGE_FORMAT_A16: case KINC_IMAGE_FORMAT_GREY8: return GL_RED; + case KINC_IMAGE_FORMAT_R32UI: + return GL_RED_INTEGER; } } @@ -132,6 +134,8 @@ static int convertInternalFormat(kinc_image_format_t format) { #else return GL_R8; #endif + case KINC_IMAGE_FORMAT_R32UI: + return GL_R32UI; } } @@ -145,6 +149,8 @@ static int convertType(kinc_image_format_t format) { case KINC_IMAGE_FORMAT_RGBA32: default: return GL_UNSIGNED_BYTE; + case KINC_IMAGE_FORMAT_R32UI: + return GL_UNSIGNED_INT; } } @@ -483,7 +489,7 @@ void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, i glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glCheckErrors(); - glTexImage3D(GL_TEXTURE_3D, 0, convertInternalFormat(format), width, height, depth, 0, convertFormat(format), GL_UNSIGNED_BYTE, NULL); + glTexImage3D(GL_TEXTURE_3D, 0, convertInternalFormat(format), width, height, depth, 0, convertFormat(format), convertType(format), NULL); glCheckErrors(); #endif } @@ -523,8 +529,8 @@ void Kinc_G4_Internal_TextureSet(kinc_g4_texture_t *texture, kinc_g4_texture_uni #else glBindTexture(target, texture->impl.texture); glCheckErrors(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, Kinc_G4_Internal_TextureAddressingU(unit)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, Kinc_G4_Internal_TextureAddressingV(unit)); + glTexParameteri(target, GL_TEXTURE_WRAP_S, Kinc_G4_Internal_TextureAddressingU(unit)); + glTexParameteri(target, GL_TEXTURE_WRAP_T, Kinc_G4_Internal_TextureAddressingV(unit)); #endif } @@ -532,7 +538,7 @@ void Kinc_G4_Internal_TextureImageSet(kinc_g4_texture_t *texture, kinc_g4_textur #if defined(KINC_WINDOWS) || (defined(KINC_LINUX) && defined(GL_VERSION_4_4)) for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) { if (unit.stages[i] >= 0) { - glBindImageTexture(unit.stages[i], texture->impl.texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, convertInternalFormat(texture->format)); + glBindImageTexture(unit.stages[i], texture->impl.texture, 0, GL_FALSE, 0, GL_READ_WRITE, convertInternalFormat(texture->format)); } } glCheckErrors(); diff --git a/Kha/Kore/Backends/System/Windows/Sources/kinc/backend/window.c.h b/Kha/Kore/Backends/System/Windows/Sources/kinc/backend/window.c.h index b22d6238..a3d13571 100644 --- a/Kha/Kore/Backends/System/Windows/Sources/kinc/backend/window.c.h +++ b/Kha/Kore/Backends/System/Windows/Sources/kinc/backend/window.c.h @@ -392,6 +392,11 @@ void kinc_window_hide(int window_index) { UpdateWindow(windows[window_index].handle); } +void kinc_window_set_foreground(int window_index) { + SetForegroundWindow(windows[window_index].handle); + SetFocus(windows[window_index].handle); +} + void kinc_window_set_title(int window_index, const char *title) { wchar_t buffer[1024]; MultiByteToWideChar(CP_UTF8, 0, title, -1, buffer, 1024); diff --git a/Kha/Kore/Sources/kinc/graphics4/graphics.h b/Kha/Kore/Sources/kinc/graphics4/graphics.h index 8f1c2414..2441861f 100644 --- a/Kha/Kore/Sources/kinc/graphics4/graphics.h +++ b/Kha/Kore/Sources/kinc/graphics4/graphics.h @@ -376,6 +376,8 @@ KINC_FUNC void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_t /// The texture to assign to the unit KINC_FUNC void kinc_g4_set_image_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture); +KINC_FUNC void kinc_g4_set_image_render_target(kinc_g4_texture_unit_t unit, struct kinc_g4_render_target *render_target); + KINC_FUNC bool kinc_g4_init_occlusion_query(unsigned *occlusionQuery); KINC_FUNC void kinc_g4_delete_occlusion_query(unsigned occlusionQuery); diff --git a/Kha/Kore/Sources/kinc/image.h b/Kha/Kore/Sources/kinc/image.h index c98e12fa..f128865c 100644 --- a/Kha/Kore/Sources/kinc/image.h +++ b/Kha/Kore/Sources/kinc/image.h @@ -30,7 +30,8 @@ typedef enum kinc_image_format { KINC_IMAGE_FORMAT_RGBA64, KINC_IMAGE_FORMAT_A32, KINC_IMAGE_FORMAT_BGRA32, - KINC_IMAGE_FORMAT_A16 + KINC_IMAGE_FORMAT_A16, + KINC_IMAGE_FORMAT_R32UI } kinc_image_format_t; typedef struct kinc_image { @@ -608,6 +609,8 @@ int kinc_image_format_sizeof(kinc_image_format_t format) { return 1; case KINC_IMAGE_FORMAT_RGB24: return 3; + case KINC_IMAGE_FORMAT_R32UI: + return 4; } return -1; } diff --git a/Kha/Kore/Sources/kinc/window.h b/Kha/Kore/Sources/kinc/window.h index 966053bb..8905b2b2 100644 --- a/Kha/Kore/Sources/kinc/window.h +++ b/Kha/Kore/Sources/kinc/window.h @@ -139,6 +139,11 @@ KINC_FUNC void kinc_window_show(int window); /// KINC_FUNC void kinc_window_hide(int window); +/// +/// Brings a window to the foreground and sets focus to it. +/// +KINC_FUNC void kinc_window_set_foreground(int window); + /// /// Sets the title of a window. /// diff --git a/Kha/Sources/kha/compute/Access.hx b/Kha/Sources/kha/compute/Access.hx new file mode 100644 index 00000000..5fba3024 --- /dev/null +++ b/Kha/Sources/kha/compute/Access.hx @@ -0,0 +1,7 @@ +package kha.compute; + +enum abstract Access(Int) to Int { + var Read = 0; + var Write = 1; + var ReadWrite = 2; +} diff --git a/Kha/Sources/kha/compute/Compute.hx b/Kha/Sources/kha/compute/Compute.hx new file mode 100644 index 00000000..551bf6ff --- /dev/null +++ b/Kha/Sources/kha/compute/Compute.hx @@ -0,0 +1,41 @@ +package kha.compute; + +import kha.arrays.Float32Array; +import kha.Image; +import kha.FastFloat; +import kha.math.FastMatrix3; +import kha.math.FastMatrix4; +import kha.math.FastVector2; +import kha.math.FastVector3; +import kha.math.FastVector4; +import kha.graphics4.CubeMap; +import kha.graphics4.TextureAddressing; +import kha.graphics4.TextureFilter; +import kha.graphics4.MipMapFilter; + +extern class Compute { + public static function setBool(location: ConstantLocation, value: Bool): Void; + public static function setInt(location: ConstantLocation, value: Int): Void; + public static function setFloat(location: ConstantLocation, value: FastFloat): Void; + public static function setFloat2(location: ConstantLocation, value1: FastFloat, value2: FastFloat): Void; + public static function setFloat3(location: ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat): Void; + public static function setFloat4(location: ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat, value4: FastFloat): Void; + public static function setFloats(location: ConstantLocation, values: Float32Array): Void; + public static function setVector2(location: ConstantLocation, value: FastVector2): Void; + public static function setVector3(location: ConstantLocation, value: FastVector3): Void; + public static function setVector4(location: ConstantLocation, value: FastVector4): Void; + public static function setMatrix(location: ConstantLocation, value: FastMatrix4): Void; + public static function setMatrix3(location: ConstantLocation, value: FastMatrix3): Void; + public static function setBuffer(buffer: ShaderStorageBuffer, index: Int): Void; + public static function setTexture(unit: TextureUnit, texture: Image, access: Access): Void; + public static function setSampledTexture(unit: TextureUnit, texture: Image): Void; + public static function setSampledDepthTexture(unit: TextureUnit, texture: Image): Void; + public static function setSampledCubeMap(unit: TextureUnit, cubeMap: CubeMap): Void; + public static function setSampledDepthCubeMap(unit: TextureUnit, cubeMap: CubeMap): Void; + public static function setTextureParameters(unit: TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing, + minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void; + public static function setTexture3DParameters(unit: TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing, + wAddressing: TextureAddressing, minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void; + public static function setShader(shader: Shader): Void; + public static function compute(x: Int, y: Int, z: Int): Void; +} diff --git a/Kha/Sources/kha/compute/ConstantLocation.hx b/Kha/Sources/kha/compute/ConstantLocation.hx new file mode 100644 index 00000000..0c075275 --- /dev/null +++ b/Kha/Sources/kha/compute/ConstantLocation.hx @@ -0,0 +1,3 @@ +package kha.compute; + +interface ConstantLocation {} diff --git a/Kha/Sources/kha/compute/Shader.hx b/Kha/Sources/kha/compute/Shader.hx new file mode 100644 index 00000000..e1362e37 --- /dev/null +++ b/Kha/Sources/kha/compute/Shader.hx @@ -0,0 +1,10 @@ +package kha.compute; + +import kha.Blob; + +extern class Shader { + public function new(sources: Array, files: Array); + public function delete(): Void; + public function getConstantLocation(name: String): ConstantLocation; + public function getTextureUnit(name: String): TextureUnit; +} diff --git a/Kha/Sources/kha/compute/ShaderStorageBuffer.hx b/Kha/Sources/kha/compute/ShaderStorageBuffer.hx new file mode 100644 index 00000000..15dfab80 --- /dev/null +++ b/Kha/Sources/kha/compute/ShaderStorageBuffer.hx @@ -0,0 +1,12 @@ +package kha.compute; + +import kha.graphics4.VertexData; + +extern class ShaderStorageBuffer { + public function new(indexCount: Int, type: VertexData); + public function delete(): Void; + public function lock(): Array; + public function unlock(): Void; + public function set(): Void; + public function count(): Int; +} diff --git a/Kha/Sources/kha/compute/TextureUnit.hx b/Kha/Sources/kha/compute/TextureUnit.hx new file mode 100644 index 00000000..f5fbd666 --- /dev/null +++ b/Kha/Sources/kha/compute/TextureUnit.hx @@ -0,0 +1,3 @@ +package kha.compute; + +interface TextureUnit {} diff --git a/Kha/Sources/kha/graphics4/TextureFormat.hx b/Kha/Sources/kha/graphics4/TextureFormat.hx index ce2db747..0e401f22 100644 --- a/Kha/Sources/kha/graphics4/TextureFormat.hx +++ b/Kha/Sources/kha/graphics4/TextureFormat.hx @@ -8,4 +8,5 @@ enum abstract TextureFormat(Int) to Int { var RGBA64 = 4; // Half floats var A32 = 5; // Float var A16 = 6; // Half float + var R32UI = 7; // Unsigned 32-bit integer } diff --git a/Krom/Krom_opengl.exe b/Krom/Krom_opengl.exe index b22142ca..380b8415 100644 Binary files a/Krom/Krom_opengl.exe and b/Krom/Krom_opengl.exe differ diff --git a/leenkx/Shaders/std/conetrace.glsl b/leenkx/Shaders/std/conetrace.glsl index 9aeb03b9..a80ff047 100644 --- a/leenkx/Shaders/std/conetrace.glsl +++ b/leenkx/Shaders/std/conetrace.glsl @@ -110,7 +110,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori float diam = max(voxelSize0, dist * coneCoefficient); float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1); float clipmap_index = floor(lod); - float clipmap_blend = fract(lod); + float clipmap_blend = smoothstep(0.0, 1.0, fract(lod)); vec3 p0 = start_pos + dir * dist; samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution); @@ -121,11 +121,17 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori continue; } + // Edge fade: blend toward coarser clipmap near boundaries + vec3 edgeDist = min(samplePos, 1.0 - samplePos); + float minEdgeDist = min(min(edgeDist.x, edgeDist.y), edgeDist.z); + float edgeBlend = 1.0 - smoothstep(0.0, 0.1, minEdgeDist); + float totalBlend = max(clipmap_blend, edgeBlend); + mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight); - if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { + if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight); - mipSample = mix(mipSample, mipSampleNext, clipmap_blend); + mipSample = mix(mipSample, mipSampleNext, totalBlend); } sampleCol += (1.0 - sampleCol.a) * mipSample; @@ -148,9 +154,8 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) { float sum = 0.0; vec4 amount = vec4(0.0); - mat3 TBN = makeTangentBasis(normal); for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) { - vec3 coneDir = TBN * DIFFUSE_CONE_DIRECTIONS[i]; + vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i]; const float cosTheta = dot(normal, coneDir); if (cosTheta <= 0) continue; @@ -159,7 +164,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, sum += cosTheta; } - amount /= sum; + amount /= max(sum, 0.0001); amount.rgb = max(amount.rgb, vec3(0.0)); amount.a = clamp(amount.a, 0.0, 1.0); @@ -215,10 +220,10 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const float diam = max(voxelSize0, dist * coneCoefficient); float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1); float clipmap_index = floor(lod); - float clipmap_blend = fract(lod); + float clipmap_blend = smoothstep(0.0, 1.0, fract(lod)); vec3 p0 = start_pos + dir * dist; - samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x); + samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution); samplePos = samplePos * 0.5 + 0.5; if ((any(notEqual(clamp(samplePos, 0.0, 1.0), samplePos)))) { @@ -226,11 +231,17 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const continue; } + // Edge fade: blend toward coarser clipmap near boundaries + vec3 edgeDist = min(samplePos, 1.0 - samplePos); + float minEdgeDist = min(min(edgeDist.x, edgeDist.y), edgeDist.z); + float edgeBlend = 1.0 - smoothstep(0.0, 0.1, minEdgeDist); + float totalBlend = max(clipmap_blend, edgeBlend); + mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, precomputed_direction, face_offset, direction_weight); - if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { + if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight); - mipSample = mix(mipSample, mipSampleNext, clipmap_blend); + mipSample = mix(mipSample, mipSampleNext, totalBlend); } sampleCol += (1.0 - sampleCol) * mipSample; @@ -254,7 +265,7 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta; sum += cosTheta; } - amount /= sum; + amount /= max(sum, 0.0001); amount = clamp(amount, 0.0, 1.0); return amount * voxelgiOcc; } @@ -284,7 +295,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v float diam = max(voxelSize0, dist * coneCoefficient); float lod = clamp(log2(diam / voxelSize0), clipmap_index0, voxelgiClipmapCount - 1); float clipmap_index = floor(lod); - float clipmap_blend = fract(lod); + float clipmap_blend = smoothstep(0.0, 1.0, fract(lod)); vec3 p0 = start_pos + dir * dist; samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution); @@ -295,19 +306,25 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v continue; } + // Edge fade: blend toward coarser clipmap near boundaries + vec3 edgeDist = min(samplePos, 1.0 - samplePos); + float minEdgeDist = min(min(edgeDist.x, edgeDist.y), edgeDist.z); + float edgeBlend = 1.0 - smoothstep(0.0, 0.1, minEdgeDist); + float totalBlend = max(clipmap_blend, edgeBlend); + #ifdef _VoxelAOvar mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, 0, face_offset, direction_weight); #else mipSample = sampleVoxel(voxels, p0, clipmaps, clipmap_index, step_dist, 0, face_offset, direction_weight).a; #endif - if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { + if(totalBlend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { #ifdef _VoxelAOvar float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight); #else float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a; #endif - mipSample = mix(mipSample, mipSampleNext, clipmap_blend); + mipSample = mix(mipSample, mipSampleNext, totalBlend); } sampleCol += (1.0 - sampleCol) * mipSample; diff --git a/leenkx/Shaders/std/constants.glsl b/leenkx/Shaders/std/constants.glsl index cde10b48..994d17ce 100644 --- a/leenkx/Shaders/std/constants.glsl +++ b/leenkx/Shaders/std/constants.glsl @@ -24,42 +24,25 @@ const int DIFFUSE_CONE_COUNT = 16; const float SHADOW_CONE_APERTURE = radians(15.0); -const float DIFFUSE_CONE_APERTURE = 0.872665; +const float DIFFUSE_CONE_APERTURE = 1.0; -mat3 makeTangentBasis(const vec3 normal) { - // Create a tangent basis from normal vector - vec3 tangent; - vec3 bitangent; - - // Compute tangent (Frisvad's method) - if (abs(normal.z) < 0.999) { - tangent = normalize(cross(vec3(0, 1, 0), normal)); - } else { - tangent = normalize(cross(normal, vec3(1, 0, 0))); - } - bitangent = cross(normal, tangent); - - return mat3(tangent, bitangent, normal); -} - -// 16 optimized cone directions for hemisphere sampling (Z-up, normalized) const vec3 DIFFUSE_CONE_DIRECTIONS[16] = vec3[]( - vec3(0.707107, 0.000000, 0.707107), // Front - vec3(-0.707107, 0.000000, 0.707107), // Back - vec3(0.000000, 0.707107, 0.707107), // Right - vec3(0.000000, -0.707107, 0.707107), // Left - vec3(0.500000, 0.500000, 0.707107), // Front-right - vec3(-0.500000, 0.500000, 0.707107), // Back-right - vec3(0.500000, -0.500000, 0.707107), // Front-left - vec3(-0.500000, -0.500000, 0.707107),// Back-left - vec3(0.353553, 0.000000, 0.935414), // Narrow front - vec3(-0.353553, 0.000000, 0.935414), // Narrow back - vec3(0.000000, 0.353553, 0.935414), // Narrow right - vec3(0.000000, -0.353553, 0.935414), // Narrow left - vec3(0.270598, 0.270598, 0.923880), // Narrow front-right - vec3(-0.270598, 0.270598, 0.923880), // Narrow back-right - vec3(0.270598, -0.270598, 0.923880), // Narrow front-left - vec3(-0.270598, -0.270598, 0.923880) // Narrow back-left + vec3( 0.3480, 0.0000, 0.9375), + vec3(-0.4299, 0.3938, 0.8125), + vec3( 0.0635, -0.7234, 0.6875), + vec3( 0.5031, 0.6561, 0.5625), + vec3(-0.8855, -0.1566, 0.4375), + vec3( 0.8015, -0.5098, 0.3125), + vec3(-0.2550, 0.9486, 0.1875), + vec3(-0.4600, -0.8857, 0.0625), + vec3( 0.9375, 0.3424, -0.0625), + vec3(-0.9080, 0.3748, -0.1875), + vec3( 0.4026, -0.8604, -0.3125), + vec3( 0.2691, 0.8580, -0.4375), + vec3(-0.7154, -0.4146, -0.5625), + vec3( 0.7092, -0.1559, -0.6875), + vec3(-0.3353, 0.4769, -0.8125), + vec3(-0.0447, -0.3451, -0.9375) ); // TO DO - Disabled momentarily instead of changing formulas diff --git a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl b/leenkx/Shaders/voxel_light/voxel_light.comp.glsl deleted file mode 100644 index 759fc78e..00000000 --- a/leenkx/Shaders/voxel_light/voxel_light.comp.glsl +++ /dev/null @@ -1,136 +0,0 @@ -#version 450 - -layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in; - -#include "compiled.inc" -#include "std/math.glsl" -#include "std/gbuffer.glsl" -#include "std/imageatomic.glsl" -#ifdef _VoxelShadow -#include "std/conetrace.glsl" -#endif - -uniform vec3 lightPos; -uniform vec3 lightColor; -uniform int lightType; -uniform vec3 lightDir; -uniform vec2 spotData; -#ifdef _ShadowMap -uniform int lightShadow; -uniform vec2 lightProj; -uniform float shadowsBias; -uniform mat4 LVP; -#ifdef _ShadowMapAtlas -uniform int index; -uniform vec4 pointLightDataArray[maxLightsCluster * 6]; -#endif -#endif - -uniform float clipmaps[voxelgiClipmapCount * 10]; -uniform int clipmapLevel; - -uniform layout(r32ui) uimage3D voxelsLight; - -#ifdef _ShadowMap -uniform sampler2DShadow shadowMap; -uniform sampler2D shadowMapTransparent; -uniform sampler2DShadow shadowMapSpot; -#ifdef _ShadowMapAtlas -uniform sampler2DShadow shadowMapPoint; -#else -uniform samplerCubeShadow shadowMapPoint; -#endif -#endif - -#ifdef _ShadowMapAtlas -// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168 -// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/ -vec2 sampleCube(vec3 dir, out int faceIndex) { - vec3 dirAbs = abs(dir); - float ma; - vec2 uv; - if(dirAbs.z >= dirAbs.x && dirAbs.z >= dirAbs.y) { - faceIndex = dir.z < 0.0 ? 5 : 4; - ma = 0.5 / dirAbs.z; - uv = vec2(dir.z < 0.0 ? -dir.x : dir.x, -dir.y); - } - else if(dirAbs.y >= dirAbs.x) { - faceIndex = dir.y < 0.0 ? 3 : 2; - ma = 0.5 / dirAbs.y; - uv = vec2(dir.x, dir.y < 0.0 ? -dir.z : dir.z); - } - else { - faceIndex = dir.x < 0.0 ? 1 : 0; - ma = 0.5 / dirAbs.x; - uv = vec2(dir.x < 0.0 ? dir.z : -dir.z, -dir.y); - } - // downscale uv a little to hide seams - // transform coordinates from clip space to texture space - #ifndef _FlipY - return uv * 0.9976 * ma + 0.5; - #else - #ifdef HLSL - return uv * 0.9976 * ma + 0.5; - #else - return vec2(uv.x * ma, uv.y * -ma) * 0.9976 + 0.5; - #endif - #endif -} -#endif - -float lpToDepth(vec3 lp, const vec2 lightProj) { - lp = abs(lp); - float zcomp = max(lp.x, max(lp.y, lp.z)); - zcomp = lightProj.x - lightProj.y / zcomp; - return zcomp * 0.5 + 0.5; -} - -void main() { - int res = voxelgiResolution.x; - ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); - - vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; - wposition = wposition * 2.0 - 1.0; - wposition *= float(clipmaps[int(clipmapLevel * 10)]); - wposition *= voxelgiResolution.x; - wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); - - float visibility; - vec3 lp = lightPos - wposition; - vec3 l; - if (lightType == 0) { l = lightDir; visibility = 1.0; } - else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); } - -#ifdef _ShadowMap - if (lightShadow == 1) { - vec4 lightPosition = LVP * vec4(wposition, 1.0); - vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility *= texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r; - } - else if (lightShadow == 2) { - vec4 lightPosition = LVP * vec4(wposition, 1.0); - vec3 lPos = lightPosition.xyz / lightPosition.w; - visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; - } - else if (lightShadow == 3) { - #ifdef _ShadowMapAtlas - int faceIndex = 0; - const int lightIndex = index * 6; - const vec2 uv = sampleCube(-l, faceIndex); - vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas - vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; - #ifdef _FlipY - uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system - #endif - visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; - #else - visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; - #endif - } -#endif - - vec3 light = visibility * lightColor; - imageAtomicAdd(voxelsLight, dst, uint(light.r * 255)); - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(light.g * 255)); - imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(light.b * 255)); -} diff --git a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl index 75f35c59..584446ef 100644 --- a/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl +++ b/leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl @@ -43,7 +43,6 @@ uniform mat4 LVP; #endif uniform sampler3D voxelsSampler; uniform layout(r32ui) uimage3D voxels; -uniform layout(r32ui) uimage3D voxelsLight; uniform layout(rgba8) image3D voxelsB; uniform layout(rgba8) image3D voxelsOut; uniform layout(r8) image3D SDF; @@ -75,21 +74,13 @@ void main() { #endif #ifdef _VoxelGI - vec3 light = vec3(0.0); - light.r = float(imageLoad(voxelsLight, ivec3(gl_GlobalInvocationID.xyz)).r) / 255; - light.g = float(imageLoad(voxelsLight, ivec3(gl_GlobalInvocationID.xyz) + ivec3(0, 0, voxelgiResolution.x)).r) / 255; - light.b = float(imageLoad(voxelsLight, ivec3(gl_GlobalInvocationID.xyz) + ivec3(0, 0, voxelgiResolution.x * 2)).r) / 255; - light /= 3; + vec4 aniso_colors[6]; + #else + float aniso_colors[6]; #endif for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) { - #ifdef _VoxelGI - vec4 aniso_colors[6]; - #else - float aniso_colors[6]; - #endif - ivec3 src = ivec3(gl_GlobalInvocationID.xyz); src.x += i * res; ivec3 dst = src; @@ -103,30 +94,37 @@ void main() { if (i < 6) { #ifdef _VoxelGI + uint count = imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15)).r; + if (count > 0) { vec4 basecol = vec4(0.0); basecol.r = float(imageLoad(voxels, src)) / 255; basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; - basecol /= 4; + basecol /= count; vec3 emission = vec3(0.0); emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; - emission /= 3; + emission /= count; vec3 N = vec3(0.0); N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; - N /= 2; + N /= count; vec3 wnormal = decode_oct(N.rg * 2 - 1); vec3 envl = vec3(0.0); envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; - envl /= 3; + envl /= count; #ifdef _HOSEK envl *= 100; #endif + vec3 light = vec3(0.0); + light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 255; + light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 255; + light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 255; + light /= count; //clipmap to world vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; @@ -140,6 +138,7 @@ void main() { vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); radiance.rgb *= light.rgb + indirect.rgb; radiance.rgb += emission.rgb; + } #else opac = float(imageLoad(voxels, src)) / 255; diff --git a/leenkx/Sources/iron/object/MeshObject.hx b/leenkx/Sources/iron/object/MeshObject.hx index e8903c1c..f69691b2 100644 --- a/leenkx/Sources/iron/object/MeshObject.hx +++ b/leenkx/Sources/iron/object/MeshObject.hx @@ -318,9 +318,9 @@ class MeshObject extends Object { if (scontext.pipeState != lastPipeline) { g.setPipeline(scontext.pipeState); lastPipeline = scontext.pipeState; - // Uniforms.setContextConstants(g, scontext, bindParams); + Uniforms.setContextConstants(g, scontext, bindParams); } - Uniforms.setContextConstants(g, scontext, bindParams); // + //Uniforms.setContextConstants(g, scontext, bindParams); // Uniforms.setObjectConstants(g, scontext, this); if (materialContexts.length > mi) { Uniforms.setMaterialConstants(g, scontext, materialContexts[mi]); diff --git a/leenkx/Sources/leenkx/renderpath/Downsampler.hx b/leenkx/Sources/leenkx/renderpath/Downsampler.hx index 44b3491a..145e3cbb 100644 --- a/leenkx/Sources/leenkx/renderpath/Downsampler.hx +++ b/leenkx/Sources/leenkx/renderpath/Downsampler.hx @@ -62,22 +62,25 @@ abstract class Downsampler { private class DownsamplerFragment extends Downsampler { + var rtName: String; + public function new(path: RenderPath, shaderPassHandle: String, rtName: String, maxNumMips: Int) { super(path, shaderPassHandle, maxNumMips); + this.rtName = rtName; + path.loadShader(shaderPassHandle); + } - var prevScale = 1.0; - for (i in 0...maxNumMips) { + function ensureMipTarget(i: Int): RenderTarget { + if (mipmaps[i] == null) { var t = new RenderTargetRaw(); t.name = rtName + "_mip_" + i; t.width = 0; t.height = 0; - t.scale = (prevScale *= 0.5); + t.scale = Math.pow(0.5, i + 1); t.format = Inc.getHdrFormat(); - mipmaps[i] = path.createRenderTarget(t); } - - path.loadShader(shaderPassHandle); + return mipmaps[i]; } public function dispatch(srcImageName: String, numMips: Int = 0) { @@ -95,9 +98,10 @@ private class DownsamplerFragment extends Downsampler { Downsampler.numMipLevels = numMips; for (i in 0...numMips) { Downsampler.currentMipLevel = i; - path.setTarget(mipmaps[i].raw.name); + var mip = ensureMipTarget(i); + path.setTarget(mip.raw.name); path.clearTarget(); - path.bindTarget(i == 0 ? srcImageName : mipmaps[i - 1].raw.name, "tex"); + path.bindTarget(i == 0 ? srcImageName : ensureMipTarget(i - 1).raw.name, "tex"); path.drawShader(shaderPassHandle); } } diff --git a/leenkx/Sources/leenkx/renderpath/Inc.hx b/leenkx/Sources/leenkx/renderpath/Inc.hx index c02178fe..52b12594 100644 --- a/leenkx/Sources/leenkx/renderpath/Inc.hx +++ b/leenkx/Sources/leenkx/renderpath/Inc.hx @@ -2,6 +2,7 @@ package leenkx.renderpath; import iron.RenderPath; import iron.object.LightObject; +import iron.object.Clipmap; import leenkx.math.Helper; import kha.arrays.Float32Array; @@ -22,6 +23,7 @@ class Inc { #end #if (rp_voxels != "Off") + static var voxelClipmapsArray:Float32Array = null; static var voxel_sh0:kha.graphics4.ComputeShader = null; static var voxel_sh1:kha.graphics4.ComputeShader = null; static var voxel_ta0:kha.graphics4.TextureUnit; @@ -37,7 +39,6 @@ class Inc { #if (rp_voxels == "Voxel GI") static var voxel_td1:kha.graphics4.TextureUnit; static var voxel_te1:kha.graphics4.TextureUnit; - static var voxel_tf1:kha.graphics4.TextureUnit; static var voxel_cc1:kha.graphics4.ConstantLocation; #else #if lnx_voxelgi_shadows @@ -92,31 +93,6 @@ class Inc { static var voxel_cc4:kha.graphics4.ConstantLocation; static var voxel_cd4:kha.graphics4.ConstantLocation; - static var voxel_sh5:kha.graphics4.ComputeShader = null; - static var voxel_ta5:kha.graphics4.TextureUnit; - static var voxel_te5:kha.graphics4.TextureUnit; - static var voxel_tf5:kha.graphics4.TextureUnit; - static var voxel_tg5:kha.graphics4.TextureUnit; - static var voxel_ca5:kha.graphics4.ConstantLocation; - static var voxel_cb5:kha.graphics4.ConstantLocation; - static var voxel_cc5:kha.graphics4.ConstantLocation; - static var voxel_cd5:kha.graphics4.ConstantLocation; - static var voxel_ce5:kha.graphics4.ConstantLocation; - static var voxel_cf5:kha.graphics4.ConstantLocation; - static var voxel_cg5:kha.graphics4.ConstantLocation; - #if rp_shadowmap - static var voxel_tb5:kha.graphics4.TextureUnit; - static var voxel_tc5:kha.graphics4.TextureUnit; - static var voxel_td5:kha.graphics4.TextureUnit; - static var voxel_ch5:kha.graphics4.ConstantLocation; - static var voxel_ci5:kha.graphics4.ConstantLocation; - static var voxel_cj5:kha.graphics4.ConstantLocation; - static var voxel_ck5:kha.graphics4.ConstantLocation; - #if lnx_shadowmap_atlas - static var voxel_cl5:kha.graphics4.ConstantLocation; - static var voxel_cm5:kha.graphics4.ConstantLocation; - #end - #end #end //rp_voxels == "Voxel GI" #end //rp_voxels != "Off" @@ -617,9 +593,6 @@ class Inc { // Init voxels #if (rp_voxels != 'Off') initGI(); - #if (rp_voxels == "Voxel GI") - initGI("voxelsLight"); - #end #end #end // lnx_config } @@ -740,12 +713,6 @@ class Inc { t.height = res * Main.voxelgiClipmapCount; t.depth = res; } - else if (t.name == "voxelsLight") { - t.format = "R32UI"; - t.width = res; - t.height = res * Main.voxelgiClipmapCount; - t.depth = res * 3; // Store R, G, B in separate z-slices - } else if (t.name == "voxelsOut" || t.name == "voxelsOutB") { #if (rp_voxels == "Voxel AO") t.format = "R8"; @@ -877,8 +844,7 @@ class Inc { #if (rp_voxels == "Voxel GI") voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); - voxel_te1 = voxel_sh1.getTextureUnit("voxelsLight"); - voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); + voxel_te1 = voxel_sh1.getTextureUnit("SDF"); voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength"); #else #if lnx_voxelgi_shadows @@ -951,38 +917,27 @@ class Inc { voxel_cc4 = voxel_sh4.getConstantLocation("eye"); voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution"); } - if (voxel_sh5 == null) - { - voxel_sh5 = path.getComputeShader("voxel_light"); - voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight"); - voxel_te5 = voxel_sh5.getTextureUnit("voxels"); - voxel_tf5 = voxel_sh5.getTextureUnit("voxelsSampler"); - voxel_tg5 = voxel_sh5.getTextureUnit("voxelsSDFSampler"); + #end + } - voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps"); - voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel"); - - voxel_cc5 = voxel_sh5.getConstantLocation("lightPos"); - voxel_cd5 = voxel_sh5.getConstantLocation("lightColor"); - voxel_ce5 = voxel_sh5.getConstantLocation("lightType"); - voxel_cf5 = voxel_sh5.getConstantLocation("lightDir"); - voxel_cg5 = voxel_sh5.getConstantLocation("spotData"); - #if rp_shadowmap - voxel_tb5 = voxel_sh5.getTextureUnit("shadowMap"); - voxel_tc5 = voxel_sh5.getTextureUnit("shadowMapSpot"); - voxel_td5 = voxel_sh5.getTextureUnit("shadowMapPoint"); - - voxel_ch5 = voxel_sh5.getConstantLocation("lightShadow"); - voxel_ci5 = voxel_sh5.getConstantLocation("lightProj"); - voxel_cj5 = voxel_sh5.getConstantLocation("LVP"); - voxel_ck5 = voxel_sh5.getConstantLocation("shadowsBias"); - #if lnx_shadowmap_atlas - voxel_cl5 = voxel_sh5.getConstantLocation("index"); - voxel_cm5 = voxel_sh5.getConstantLocation("pointLightDataArray"); - #end - #end + public static function fillVoxelClipmapsArray(clipmaps: Array): Float32Array { + if (voxelClipmapsArray == null || voxelClipmapsArray.length != Main.voxelgiClipmapCount * 10) { + voxelClipmapsArray = new Float32Array(Main.voxelgiClipmapCount * 10); } - #end + var fa = voxelClipmapsArray; + for (i in 0...Main.voxelgiClipmapCount) { + fa[i * 10] = clipmaps[i].voxelSize; + fa[i * 10 + 1] = clipmaps[i].extents.x; + fa[i * 10 + 2] = clipmaps[i].extents.y; + fa[i * 10 + 3] = clipmaps[i].extents.z; + fa[i * 10 + 4] = clipmaps[i].center.x; + fa[i * 10 + 5] = clipmaps[i].center.y; + fa[i * 10 + 6] = clipmaps[i].center.z; + fa[i * 10 + 7] = clipmaps[i].offset_prev.x; + fa[i * 10 + 8] = clipmaps[i].offset_prev.y; + fa[i * 10 + 9] = clipmaps[i].offset_prev.z; + } + return fa; } public static function computeVoxelsOffsetPrev(g: kha.graphics4.Graphics) { @@ -996,19 +951,7 @@ class Inc { g.setImageTexture(voxel_ta0, rts.get("voxelsOut").image); g.setImageTexture(voxel_tb0, rts.get("voxelsOutB").image); - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } + var fa = fillVoxelClipmapsArray(clipmaps); g.setFloats(voxel_ca0, fa); @@ -1029,7 +972,6 @@ class Inc { if (rts.get("voxelsOut") == null) initGI("voxelsOut"); if (rts.get("voxelsOutB") == null) initGI("voxelsOutB"); #if (rp_voxels == "Voxel GI") - if (rts.get("voxelsLight") == null) initGI("voxelsLight"); if (rts.get("voxelsSDF") == null) initGI("voxelsSDF"); #elseif lnx_voxelgi_shadows if (rts.get("voxelsSDF") == null) initGI("voxelsSDF"); @@ -1045,8 +987,7 @@ class Inc { g.setImageTexture(voxel_tc1, rts.get("voxelsOut").image); #if (rp_voxels == "Voxel GI") g.setTexture(voxel_td1, rts.get("voxelsOutB").image); - g.setImageTexture(voxel_te1, rts.get("voxelsLight").image); - g.setImageTexture(voxel_tf1, rts.get("voxelsSDF").image); + g.setImageTexture(voxel_te1, rts.get("voxelsSDF").image); g.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength); #else #if lnx_voxelgi_shadows @@ -1054,19 +995,7 @@ class Inc { #end #end - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } + var fa = fillVoxelClipmapsArray(clipmaps); g.setFloats(voxel_ca1, fa); @@ -1084,6 +1013,8 @@ class Inc { var clipmaps = iron.RenderPath.clipmaps; var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; + if (rts.get("voxelsSDF") == null || rts.get("voxelsSDFtmp") == null) return; + var read_sdf = "voxelsSDF"; var write_sdf = "voxelsSDFtmp"; @@ -1095,19 +1026,7 @@ class Inc { g.setImageTexture(voxel_ta2, rts.get(read_sdf).image); g.setImageTexture(voxel_tb2, rts.get(write_sdf).image); - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (j in 0...Main.voxelgiClipmapCount) { - fa[j * 10] = clipmaps[j].voxelSize; - fa[j * 10 + 1] = clipmaps[j].extents.x; - fa[j * 10 + 2] = clipmaps[j].extents.y; - fa[j * 10 + 3] = clipmaps[j].extents.z; - fa[j * 10 + 4] = clipmaps[j].center.x; - fa[j * 10 + 5] = clipmaps[j].center.y; - fa[j * 10 + 6] = clipmaps[j].center.z; - fa[j * 10 + 7] = clipmaps[j].offset_prev.x; - fa[j * 10 + 8] = clipmaps[j].offset_prev.y; - fa[j * 10 + 9] = clipmaps[j].offset_prev.z; - } + var fa = fillVoxelClipmapsArray(clipmaps); g.setFloats(voxel_ca2, fa); @@ -1124,6 +1043,18 @@ class Inc { write_sdf = write_sdf == "voxelsSDF" ? "voxelsSDFtmp" : "voxelsSDF"; } } + + // If passcount is odd, result is in voxelsSDFtmp but consumers read voxelsSDF + if (passcount % 2 != 0) { + g.setComputeShader(voxel_sh2); + g.setImageTexture(voxel_ta2, rts.get("voxelsSDFtmp").image); + g.setImageTexture(voxel_tb2, rts.get("voxelsSDF").image); + fillVoxelClipmapsArray(clipmaps); + g.setFloats(voxel_ca2, voxelClipmapsArray); + g.setInt(voxel_cb2, iron.RenderPath.clipmapLevel); + g.setFloat(voxel_cc2, 1.0); + g.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); + } } #end @@ -1153,19 +1084,7 @@ class Inc { g.setTexture(voxel_th3, iron.Scene.active.world.probe.radiance); #end - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } + var fa = fillVoxelClipmapsArray(clipmaps); g.setFloats(voxel_ca3, fa); @@ -1248,19 +1167,7 @@ class Inc { g.setTexture(voxel_th3, iron.Scene.active.world.probe.radiance); #end - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } + var fa = fillVoxelClipmapsArray(clipmaps); g.setFloats(voxel_ca3, fa); @@ -1338,19 +1245,7 @@ class Inc { g.setTexture(voxel_tf4, rts.get("gbuffer2").image); #end - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (i in 0...Main.voxelgiClipmapCount) { - fa[i * 10] = clipmaps[i].voxelSize; - fa[i * 10 + 1] = clipmaps[i].extents.x; - fa[i * 10 + 2] = clipmaps[i].extents.y; - fa[i * 10 + 3] = clipmaps[i].extents.z; - fa[i * 10 + 4] = clipmaps[i].center.x; - fa[i * 10 + 5] = clipmaps[i].center.y; - fa[i * 10 + 6] = clipmaps[i].center.z; - fa[i * 10 + 7] = clipmaps[i].offset_prev.x; - fa[i * 10 + 8] = clipmaps[i].offset_prev.y; - fa[i * 10 + 9] = clipmaps[i].offset_prev.z; - } + var fa = fillVoxelClipmapsArray(clipmaps); g.setFloats(voxel_ca4, fa); @@ -1385,147 +1280,6 @@ class Inc { } #if (rp_voxels == "Voxel GI") - public static function computeVoxelsLight(g: kha.graphics4.Graphics) { - var rts = path.renderTargets; - var res = iron.RenderPath.getVoxelRes(); - var camera = iron.Scene.active.camera; - var clipmaps = iron.RenderPath.clipmaps; - var clipmap = clipmaps[iron.RenderPath.clipmapLevel]; - var lights = iron.Scene.active.lights; - - var lightIndex = 0; - for (i in 0...lights.length) { - var l = lights[i]; - if (!l.visible) continue; - path.light = l; - - g.setComputeShader(voxel_sh5); - - g.setImageTexture(voxel_ta5, rts.get("voxelsLight").image); - g.setImageTexture(voxel_te5, rts.get("voxels").image); - g.setTexture(voxel_tf5, rts.get("voxelsOut").image); - g.setTexture(voxel_tg5, rts.get("voxelsSDF").image); - - var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); - for (j in 0...Main.voxelgiClipmapCount) { - fa[j * 10] = clipmaps[j].voxelSize; - fa[j * 10 + 1] = clipmaps[j].extents.x; - fa[j * 10 + 2] = clipmaps[j].extents.y; - fa[j * 10 + 3] = clipmaps[j].extents.z; - fa[j * 10 + 4] = clipmaps[j].center.x; - fa[j * 10 + 5] = clipmaps[j].center.y; - fa[j * 10 + 6] = clipmaps[j].center.z; - fa[j * 10 + 7] = clipmaps[j].offset_prev.x; - fa[j * 10 + 8] = clipmaps[j].offset_prev.y; - fa[j * 10 + 9] = clipmaps[j].offset_prev.z; - } - - g.setFloats(voxel_ca5, fa); - - g.setInt(voxel_cb5, iron.RenderPath.clipmapLevel); - - #if rp_shadowmap - if (l.data.raw.type == "sun") { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - g.setTexture(voxel_tb5, rts.get("shadowMapAtlas").image); - #else - g.setTexture(voxel_tb5, rts.get("shadowMapAtlasSun").image); - #end - #else - g.setTexture(voxel_tb5, rts.get("shadowMap").image); - #end - g.setInt(voxel_ch5, 1); // lightShadow - } - else if (l.data.raw.type == "spot" || l.data.raw.type == "area") { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - g.setTexture(voxel_tc5, rts.get("shadowMapAtlas").image); - #else - g.setTexture(voxel_tc5, rts.get("shadowMapAtlasSpot").image); - #end - #else - g.setTexture(voxel_tc5, rts.get("shadowMapSpot[" + lightIndex + "]").image); - #end - g.setInt(voxel_ch5, 2); - } - else { - #if lnx_shadowmap_atlas - #if lnx_shadowmap_atlas_single_map - g.setTexture(voxel_td5, rts.get("shadowMapAtlas").image); - #else - g.setTexture(voxel_td5, rts.get("shadowMapAtlasPoint").image); - g.setInt(voxel_cl5, i); - g.setFloats(voxel_cm5, iron.object.LightObject.pointLightsData); - #end - #else - g.setCubeMap(voxel_td5, rts.get("shadowMapPoint[" + lightIndex + "]").cubeMap); - #end - g.setInt(voxel_ch5, 3); - } - - // lightProj - var near = l.data.raw.near_plane; - var far = l.data.raw.far_plane; - var a:kha.FastFloat = far + near; - var b:kha.FastFloat = far - near; - var f2:kha.FastFloat = 2.0; - var c:kha.FastFloat = f2 * far * near; - var vx:kha.FastFloat = a / b; - var vy:kha.FastFloat = c / b; - g.setFloat2(voxel_ci5, vx, vy); - // LVP - m.setFrom(l.VP); - m.multmat(iron.object.Uniforms.biasMat); - #if lnx_shadowmap_atlas - if (l.data.raw.type == "sun") - { - // tile matrix - m.setIdentity(); - // scale [0-1] coords to [0-tilescale] - m._00 = l.tileScale[0]; - m._11 = l.tileScale[0]; - // offset coordinate start from [0, 0] to [tile-start-x, tile-start-y] - m._30 = l.tileOffsetX[0]; - m._31 = l.tileOffsetY[0]; - m.multmat(m); - #if (!kha_opengl) - m.setIdentity(); - m._11 = -1.0; - m._31 = 1.0; - m.multmat(m); - #end - } - #end - g.setMatrix(voxel_cj5, m.self); - // shadowsBias - g.setFloat(voxel_ck5, l.data.raw.shadows_bias); - #end // rp_shadowmap - - // lightPos - g.setFloat3(voxel_cc5, l.transform.worldx(), l.transform.worldy(), l.transform.worldz()); - // lightCol - var f = l.data.raw.strength; - g.setFloat3(voxel_cd5, l.data.raw.color[0] * f, l.data.raw.color[1] * f, l.data.raw.color[2] * f); - // lightType - g.setInt(voxel_ce5, iron.data.LightData.typeToInt(l.data.raw.type)); - // lightDir - var v = l.look(); - g.setFloat3(voxel_cf5, v.x, v.y, v.z); - // spotData - if (l.data.raw.type == "spot") { - var vx = l.data.raw.spot_size; - var vy = vx - l.data.raw.spot_blend; - g.setFloat2(voxel_cg5, vx, vy); - } - - g.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); - - if (!iron.object.LightObject.discardLightCulled(l)) { - lightIndex++; - } - } - } #end // GI #end // Voxels } @@ -1881,7 +1635,8 @@ class ShadowMapTile { if (size < oldTile.size) { oldTile.forEachTileLinked(function(lTile) { var childTile = findFreeChildTile(lTile, size); - tilesFound.push(childTile); + if (childTile != null) + tilesFound.push(childTile); }); } // reuse parent tiles @@ -1910,6 +1665,7 @@ class ShadowMapTile { while (size < childrenTile.size) { childrenTile = childrenTile.tiles[0]; } + if (childrenTile.light != null) return null; return childrenTile; } diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx index b672216d..b1363543 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx @@ -675,7 +675,10 @@ class RenderPathDeferred { if (leenkx.data.Config.raw.rp_gi != false) { var path = RenderPath.active; - // TODO: investigate currentTarget + #if rp_probes + if (!path.isProbe) { + #end + // TODO: investigate currentTarget var g = path.frameG; Inc.computeVoxelsBegin(g); @@ -716,11 +719,11 @@ class RenderPathDeferred { Inc.computeVoxelsTemporal(g); - #if (rp_voxels == "Voxel GI") - Inc.computeVoxelsLight(g); + #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) Inc.computeVoxelsSDF(g); #end + if (iron.RenderPath.res_pre_clear == true) { iron.RenderPath.res_pre_clear = false; #if (rp_voxels == "Voxel GI") @@ -731,6 +734,9 @@ class RenderPathDeferred { #end } } + #if rp_probes + } + #end #end // --- // Deferred light @@ -778,16 +784,25 @@ class RenderPathDeferred { #if (rp_voxels != "Off") if (leenkx.data.Config.raw.rp_gi != false) { + #if rp_probes + if (!path.isProbe) { + #end var g = path.frameG; #if (lnx_config && (rp_voxels == "Voxel AO")) voxelao_pass = true; #end #if (rp_voxels == "Voxel AO") Inc.resolveAO(g); - path.bindTarget("voxels_ao", "voxels_ao"); #else Inc.resolveDiffuse(g); Inc.resolveSpecular(g); + #end + #if rp_probes + } + #end + #if (rp_voxels == "Voxel AO") + path.bindTarget("voxels_ao", "voxels_ao"); + #else path.bindTarget("voxels_diffuse", "voxels_diffuse"); path.bindTarget("voxels_specular", "voxels_specular"); #end @@ -997,15 +1012,19 @@ class RenderPathDeferred { path.drawMeshes("refraction"); - path.setTarget("tex"); - path.bindTarget("refr", "tex"); + path.setTarget("buf"); + path.bindTarget("tex", "tex"); path.bindTarget("gbufferD1", "gbufferD1"); path.bindTarget("gbuffer0", "gbuffer0"); - path.bindTarget("gbuffer1", "tex1"); + path.bindTarget("refr", "tex1"); path.bindTarget("_main", "gbufferD"); path.bindTarget("gbuffer_refraction", "gbuffer_refraction"); path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass"); + + path.setTarget("tex"); + path.bindTarget("buf", "tex"); + path.drawShader("shader_datas/copy_pass/copy_pass"); } } #end diff --git a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx index d9c6b8e4..ea61677b 100644 --- a/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx +++ b/leenkx/Sources/leenkx/renderpath/RenderPathForward.hx @@ -420,8 +420,13 @@ class RenderPathForward { if (leenkx.data.Config.raw.rp_gi != false) { var path = RenderPath.active; + #if rp_probes + if (!path.isProbe) { + #end - Inc.computeVoxelsBegin(); + var g = path.frameG; + + Inc.computeVoxelsBegin(g); if (iron.RenderPath.pre_clear == true) { @@ -437,7 +442,7 @@ class RenderPathForward { else { path.clearImage("voxels", 0x00000000); - Inc.computeVoxelsOffsetPrev(); + Inc.computeVoxelsOffsetPrev(g); } path.setTarget(""); @@ -458,16 +463,15 @@ class RenderPathForward { path.drawMeshes("voxel"); - Inc.computeVoxelsTemporal(); - - #if (rp_voxels == "Voxel GI") - Inc.computeVoxelsLight(); - #end + Inc.computeVoxelsTemporal(g); #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) - Inc.computeVoxelsSDF(); + Inc.computeVoxelsSDF(g); #end } + #if rp_probes + } + #end #end RenderPathCreator.setTargetMeshes(); diff --git a/leenkx/blender/lnx/make_renderpath.py b/leenkx/blender/lnx/make_renderpath.py index 12d10234..c2a838a4 100644 --- a/leenkx/blender/lnx/make_renderpath.py +++ b/leenkx/blender/lnx/make_renderpath.py @@ -141,7 +141,6 @@ def add_world_defs(): if voxelgi: assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl') assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl') - assets.add_shader_external(lnx.utils.get_sdk_path() + '/leenkx/Shaders/voxel_light/voxel_light.comp.glsl') wrd.world_defs += '_VoxelGI' if rpdat.lnx_voxelgi_refract: wrd.world_defs += '_VoxelRefract' diff --git a/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py b/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py index 26984947..3c27a48c 100644 --- a/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py +++ b/leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py @@ -379,6 +379,7 @@ def parse_sky_hosekwilkie(node: bpy.types.ShaderNodeTexSky, state: ParserState) # Radiance if rpdat.lnx_radiance and rpdat.lnx_irradiance and not mobile_mat: wrd.world_defs += '_Rad' + assets.add_khafile_def("lnx_radiance") hosek_path = 'leenkx/Assets/hosek/' sdk_path = lnx.utils.get_sdk_path() # Use fake maps for now @@ -556,6 +557,7 @@ def parse_tex_environment(node: bpy.types.ShaderNodeTexEnvironment, out_socket: # Append radiance define if rpdat.lnx_irradiance and rpdat.lnx_radiance and not mobile_mat: wrd.world_defs += '_Rad' + assets.add_khafile_def("lnx_radiance") return 'texture(envmap, envMapEquirect(pos)).rgb * envmapStrength'