forked from Onek8/LNXSDK
Compare commits
22 Commits
91b6c203e9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| cbbcd053fb | |||
| 160f6bdadf | |||
| 50ad462318 | |||
| 1239145da4 | |||
| 102941b5d2 | |||
| defff993a0 | |||
| e408151295 | |||
| 22159c9f37 | |||
| 9a2779982d | |||
| 2fc7e9880a | |||
| 7e1ac5fa5c | |||
| b2395f30fc | |||
| f4b0bf1e93 | |||
| 31a6a9d7ec | |||
| 7b2f21c499 | |||
| 17c31b4a4b | |||
| 013c8653ff | |||
| bd8b49a416 | |||
| 9d83c318b6 | |||
| cb19c9b5b4 | |||
| f4fe822ef6 | |||
| 6689fbc734 |
@ -142,6 +142,8 @@ class Image implements Canvas implements Resource {
|
||||
return 5;
|
||||
case A16:
|
||||
return 7;
|
||||
case R32UI:
|
||||
return 8;
|
||||
default:
|
||||
return 1; // Grey8
|
||||
}
|
||||
|
||||
@ -234,6 +234,8 @@ class Image implements Canvas implements Resource {
|
||||
return 5;
|
||||
case A16:
|
||||
return 7;
|
||||
case R32UI:
|
||||
return 8;
|
||||
default:
|
||||
return 1; // Grey8
|
||||
}
|
||||
|
||||
@ -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,
|
||||
@ -159,4 +160,45 @@ extern class Krom {
|
||||
static function getConstantLocationCompute(shader: Dynamic, name: String): Dynamic;
|
||||
static function getTextureUnitCompute(shader: Dynamic, name: String): Dynamic;
|
||||
static function compute(x: Int, y: Int, z: Int): Void;
|
||||
static function webviewCreate(options: Dynamic): Int;
|
||||
static function webviewLoadHTML(id: Int, html: String): Void;
|
||||
static function webviewLoadURL(id: Int, url: String): Void;
|
||||
static function webviewEvalJS(id: Int, js: String): Void;
|
||||
static function webviewEvalJSAsync(id: Int, js: String, callback: String->Void): Void;
|
||||
static function webviewShow(id: Int): Void;
|
||||
static function webviewHide(id: Int): Void;
|
||||
static function webviewDestroy(id: Int): Void;
|
||||
static function webviewResize(id: Int, width: Int, height: Int): Void;
|
||||
static function webviewMove(id: Int, x: Int, y: Int): Void;
|
||||
static function webviewSetBounds(id: Int, x: Int, y: Int, width: Int, height: Int): Void;
|
||||
static function webviewGetX(id: Int): Int;
|
||||
static function webviewGetY(id: Int): Int;
|
||||
static function webviewGetWidth(id: Int): Int;
|
||||
static function webviewGetHeight(id: Int): Int;
|
||||
static function webviewSetTransparent(id: Int, transparent: Bool): Void;
|
||||
static function webviewSetClickThrough(id: Int, enabled: Bool): Void;
|
||||
static function webviewSetTitle(id: Int, title: String): Void;
|
||||
static function webviewSend(id: Int, message: String): Void;
|
||||
static function webviewSetOnMessage(id: Int, callback: String->Void): Void;
|
||||
static function webviewSetOnLoad(id: Int, callback: Void->Void): Void;
|
||||
static function webviewSetOnError(id: Int, callback: String->Void): Void;
|
||||
static function webviewSetOnClose(id: Int, callback: Void->Void): Void;
|
||||
static function webviewCount(): Int;
|
||||
static function webviewIsValid(id: Int): Bool;
|
||||
static function webviewSetActiveDOM(id: Int): Void;
|
||||
static function webviewGetActiveDOM(): Int;
|
||||
static function webviewGoBack(id: Int): Void;
|
||||
static function webviewGoForward(id: Int): Void;
|
||||
static function webviewReload(id: Int): Void;
|
||||
static function webviewCanGoBack(id: Int): Bool;
|
||||
static function webviewCanGoForward(id: Int): Bool;
|
||||
static function webviewGetURL(id: Int): String;
|
||||
static function webviewGetPageTitle(id: Int): String;
|
||||
static function webviewMinimize(id: Int): Void;
|
||||
static function webviewMaximize(id: Int): Void;
|
||||
static function webviewRestore(id: Int): Void;
|
||||
static function webviewSetFullscreen(id: Int, fullscreen: Bool): Void;
|
||||
static function webviewIsFullscreen(id: Int): Bool;
|
||||
static function webviewEnableDevTools(id: Int, enabled: Bool): Void;
|
||||
static function webviewSetContextMenu(id: Int, enabled: Bool): Void;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -9,14 +9,7 @@ class ShaderStorageBuffer {
|
||||
public function new(indexCount: Int, type: VertexData) {
|
||||
myCount = indexCount;
|
||||
data = new Array<Int>();
|
||||
data[myCount - 1] = 0;
|
||||
init(indexCount, type);
|
||||
}
|
||||
|
||||
function init(indexCount: Int, type: VertexData) {
|
||||
myCount = indexCount;
|
||||
data = new Array<Int>();
|
||||
data[myCount - 1] = 0;
|
||||
if (myCount > 0) data[myCount - 1] = 0;
|
||||
}
|
||||
|
||||
public function delete(): Void {}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -376,6 +376,8 @@ KINC_FUNC void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_t
|
||||
/// <param name="texture">The texture to assign to the unit</param>
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -139,6 +139,11 @@ KINC_FUNC void kinc_window_show(int window);
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_window_hide(int window);
|
||||
|
||||
/// <summary>
|
||||
/// Brings a window to the foreground and sets focus to it.
|
||||
/// </summary>
|
||||
KINC_FUNC void kinc_window_set_foreground(int window);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the title of a window.
|
||||
/// </summary>
|
||||
|
||||
Binary file not shown.
7
Kha/Sources/kha/compute/Access.hx
Normal file
7
Kha/Sources/kha/compute/Access.hx
Normal file
@ -0,0 +1,7 @@
|
||||
package kha.compute;
|
||||
|
||||
enum abstract Access(Int) to Int {
|
||||
var Read = 0;
|
||||
var Write = 1;
|
||||
var ReadWrite = 2;
|
||||
}
|
||||
41
Kha/Sources/kha/compute/Compute.hx
Normal file
41
Kha/Sources/kha/compute/Compute.hx
Normal file
@ -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;
|
||||
}
|
||||
3
Kha/Sources/kha/compute/ConstantLocation.hx
Normal file
3
Kha/Sources/kha/compute/ConstantLocation.hx
Normal file
@ -0,0 +1,3 @@
|
||||
package kha.compute;
|
||||
|
||||
interface ConstantLocation {}
|
||||
10
Kha/Sources/kha/compute/Shader.hx
Normal file
10
Kha/Sources/kha/compute/Shader.hx
Normal file
@ -0,0 +1,10 @@
|
||||
package kha.compute;
|
||||
|
||||
import kha.Blob;
|
||||
|
||||
extern class Shader {
|
||||
public function new(sources: Array<Blob>, files: Array<String>);
|
||||
public function delete(): Void;
|
||||
public function getConstantLocation(name: String): ConstantLocation;
|
||||
public function getTextureUnit(name: String): TextureUnit;
|
||||
}
|
||||
12
Kha/Sources/kha/compute/ShaderStorageBuffer.hx
Normal file
12
Kha/Sources/kha/compute/ShaderStorageBuffer.hx
Normal file
@ -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<Int>;
|
||||
public function unlock(): Void;
|
||||
public function set(): Void;
|
||||
public function count(): Int;
|
||||
}
|
||||
3
Kha/Sources/kha/compute/TextureUnit.hx
Normal file
3
Kha/Sources/kha/compute/TextureUnit.hx
Normal file
@ -0,0 +1,3 @@
|
||||
package kha.compute;
|
||||
|
||||
interface TextureUnit {}
|
||||
@ -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
|
||||
}
|
||||
|
||||
Binary file not shown.
BIN
Krom/Krom.exe
BIN
Krom/Krom.exe
Binary file not shown.
Binary file not shown.
@ -379,7 +379,7 @@ void main() {
|
||||
|
||||
#ifdef _SSGI
|
||||
vec3 ssgiColor = textureLod(ssgitex, texCoord, 0.0).rgb;
|
||||
fragColor.rgb += ssgiColor * albedo;
|
||||
fragColor.rgb += ssgiColor * basecolor;
|
||||
#endif
|
||||
|
||||
#ifdef _EmissionShadeless
|
||||
|
||||
@ -28,10 +28,12 @@ in vec2 texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
const float GOLDEN_ANGLE = 2.39996323;
|
||||
const int RAY_STEPS = 12;
|
||||
const int RAY_STEPS = 6;
|
||||
const int BINARY_STEPS = 3;
|
||||
|
||||
vec2 getProjectedCoord(const vec3 viewPos) {
|
||||
vec4 projectedCoord = P * vec4(viewPos, 1.0);
|
||||
if (projectedCoord.w <= 0.0) return vec2(-1e5);
|
||||
projectedCoord.xy /= projectedCoord.w;
|
||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
||||
#ifdef _InvY
|
||||
@ -40,16 +42,12 @@ vec2 getProjectedCoord(const vec3 viewPos) {
|
||||
return projectedCoord.xy;
|
||||
}
|
||||
|
||||
vec3 cosineSampleHemisphere(vec3 n, vec2 rand) {
|
||||
float phi = PI * 2.0 * rand.x;
|
||||
float cosTheta = sqrt(1.0 - rand.y);
|
||||
float sinTheta = sqrt(rand.y);
|
||||
|
||||
vec3 h = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
|
||||
|
||||
vec3 tangent, bitangent;
|
||||
float linearZ(const float depth) {
|
||||
return -P[3].z / (depth + P[2].z);
|
||||
}
|
||||
|
||||
void buildTBN(vec3 n, out vec3 tangent, out vec3 bitangent) {
|
||||
vec3 absN = abs(n);
|
||||
|
||||
if (absN.x <= absN.y && absN.x <= absN.z) {
|
||||
tangent = normalize(cross(n, vec3(1.0, 0.0, 0.0)));
|
||||
} else if (absN.y <= absN.z) {
|
||||
@ -58,46 +56,70 @@ vec3 cosineSampleHemisphere(vec3 n, vec2 rand) {
|
||||
tangent = normalize(cross(n, vec3(0.0, 0.0, 1.0)));
|
||||
}
|
||||
bitangent = cross(n, tangent);
|
||||
|
||||
}
|
||||
|
||||
vec3 sampleHemisphere(vec3 n, vec3 tangent, vec3 bitangent, float phi, float cosTheta) {
|
||||
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
vec3 h = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
|
||||
return normalize(tangent * h.x + bitangent * h.y + n * h.z);
|
||||
}
|
||||
|
||||
vec3 traceRay(vec3 origin, vec3 dir, float maxDist, float minDist) {
|
||||
vec3 traceRay(vec3 origin, vec3 dir, float maxDist, float minDist, float jitter) {
|
||||
float stepSize = maxDist / float(RAY_STEPS);
|
||||
vec3 pos = origin + dir * minDist;
|
||||
float rayDist = minDist + stepSize * (jitter - 1.0);
|
||||
vec3 pos = origin + dir * rayDist;
|
||||
|
||||
float prevDepthDiff = 0.0;
|
||||
float hadValidPrev = 0.0;
|
||||
bool hasPrev = false;
|
||||
|
||||
for (int i = 1; i <= RAY_STEPS; i++) {
|
||||
for (int i = 0; i < RAY_STEPS; i++) {
|
||||
pos += dir * stepSize;
|
||||
rayDist += stepSize;
|
||||
vec2 uv = getProjectedCoord(pos);
|
||||
if (uv.x < -100.0) return vec3(-1.0);
|
||||
uv = clamp(uv, vec2(0.001), vec2(0.999));
|
||||
|
||||
vec2 sampleUV = clamp(uv, vec2(0.001), vec2(0.999));
|
||||
|
||||
float sampleDepth = textureLod(gbufferD, sampleUV, 0.0).r * 2.0 - 1.0;
|
||||
float sampleDepth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
|
||||
if (sampleDepth == 1.0) {
|
||||
hadValidPrev = 0.0;
|
||||
hasPrev = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
float depthDiff = pos.z - linearZ(sampleDepth);
|
||||
float thickness = maxDist * 0.075 + rayDist * 0.125;
|
||||
|
||||
vec3 sampleViewPos = getPosView2(invP, sampleDepth, sampleUV);
|
||||
float depthDiff = pos.z - sampleViewPos.z;
|
||||
float rayDist = length(pos - origin);
|
||||
float thickness = 0.15 + rayDist * 0.25;
|
||||
bool crossed = hasPrev && (prevDepthDiff > 0.0) && (depthDiff <= 0.0);
|
||||
bool withinThickness = (depthDiff <= 0.0) && (-depthDiff < thickness);
|
||||
|
||||
float crossed = hadValidPrev * step(0.0, prevDepthDiff) * step(depthDiff, 0.0);
|
||||
float withinThickness = step(abs(depthDiff), thickness);
|
||||
|
||||
if (crossed > 0.5 || withinThickness > 0.5) {
|
||||
float distWeight = 1.0 - (rayDist / maxDist);
|
||||
distWeight = max(0.0, distWeight * distWeight);
|
||||
if (crossed || withinThickness) {
|
||||
vec3 bPos = pos;
|
||||
vec3 bDir = dir * stepSize;
|
||||
for (int j = 0; j < BINARY_STEPS; j++) {
|
||||
bDir *= 0.5;
|
||||
bPos -= bDir;
|
||||
vec2 bUV = getProjectedCoord(bPos);
|
||||
bUV = clamp(bUV, vec2(0.001), vec2(0.999));
|
||||
float bDepth = textureLod(gbufferD, bUV, 0.0).r * 2.0 - 1.0;
|
||||
if (bDepth == 1.0) {
|
||||
bPos += bDir;
|
||||
continue;
|
||||
}
|
||||
if (bPos.z - linearZ(bDepth) > 0.0) bPos += bDir;
|
||||
}
|
||||
|
||||
return vec3(sampleUV, distWeight);
|
||||
vec2 bestUV = getProjectedCoord(bPos);
|
||||
if (bestUV.x < -100.0) return vec3(-1.0);
|
||||
bestUV = clamp(bestUV, vec2(0.001), vec2(0.999));
|
||||
|
||||
float hitDist = length(bPos - origin);
|
||||
float distWeight = max(0.0, 1.0 - (hitDist / maxDist));
|
||||
distWeight *= distWeight;
|
||||
|
||||
return vec3(bestUV, distWeight);
|
||||
}
|
||||
|
||||
prevDepthDiff = depthDiff;
|
||||
hadValidPrev = 1.0;
|
||||
hasPrev = true;
|
||||
}
|
||||
|
||||
return vec3(-1.0);
|
||||
@ -111,77 +133,77 @@ void main() {
|
||||
}
|
||||
|
||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||
vec2 enc = g0.rg;
|
||||
vec3 n;
|
||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||
n = normalize(n);
|
||||
vec3 n = getNor(g0.rg);
|
||||
vec3 basecolor = textureLod(gbuffer1, texCoord, 0.0).rgb;
|
||||
|
||||
vec3 viewNormal = V3 * n;
|
||||
vec3 viewPos = getPosView2(invP, depth, texCoord);
|
||||
|
||||
#ifdef _CPostprocess
|
||||
float radius = PPComp12.y;
|
||||
float strength = PPComp12.x;
|
||||
float radius = PPComp12.y * 2.0;
|
||||
float strength = PPComp12.x * 0.5;
|
||||
#else
|
||||
float radius = ssgiRadius;
|
||||
float strength = ssgiStrength;
|
||||
float radius = ssgiRadius * 2.0;
|
||||
float strength = ssgiStrength * 0.5;
|
||||
#endif
|
||||
|
||||
float noise = fract(52.9829189 * fract(0.06711056 * texCoord.x * 1000.0 + 0.00583715 * texCoord.y * 1000.0));
|
||||
radius = min(radius, max(-viewPos.z / P[1].y, 0.05));
|
||||
|
||||
float noise = fract(52.9829189 * fract(0.06711056 * gl_FragCoord.x + 0.00583715 * gl_FragCoord.y));
|
||||
|
||||
vec3 gi = vec3(0.0);
|
||||
int validSamples = 0;
|
||||
float missWeight = 0.0;
|
||||
|
||||
// min distance to avoid self shadowing artiffacts
|
||||
float minDist = radius * 0.05;
|
||||
|
||||
vec3 tangent, bitangent;
|
||||
buildTBN(viewNormal, tangent, bitangent);
|
||||
|
||||
for (int i = 0; i < ssgiSamples; i++) {
|
||||
float fi = float(i) + noise;
|
||||
vec2 rand = vec2(
|
||||
fract(fi * 0.7548776662 + noise),
|
||||
fract(fi * 0.5698402909 + noise * 1.5)
|
||||
);
|
||||
float phi = float(i) * GOLDEN_ANGLE + noise * PI2;
|
||||
float cosTheta = sqrt(max(0.0, 1.0 - (float(i) + 0.5) / float(ssgiSamples)));
|
||||
float jitter = fract(noise + float(i) * 0.618034);
|
||||
|
||||
vec3 rayDir = cosineSampleHemisphere(viewNormal, rand);
|
||||
vec3 hitResult = traceRay(viewPos, rayDir, radius, minDist);
|
||||
vec3 rayDir = sampleHemisphere(viewNormal, tangent, bitangent, phi, cosTheta);
|
||||
vec3 hitResult = traceRay(viewPos, rayDir, radius, minDist, jitter);
|
||||
|
||||
if (hitResult.x < 0.0) continue;
|
||||
if (hitResult.x < 0.0) {
|
||||
missWeight += 1.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
vec2 hitUV = hitResult.xy;
|
||||
float distWeight = hitResult.z;
|
||||
|
||||
vec3 hitAlbedo = textureLod(gbuffer1, hitUV, 1.0).rgb;
|
||||
vec3 hitN = getNor(textureLod(gbuffer0, hitUV, 0.0).rg);
|
||||
float emitterCos = max(0.0, dot(V3 * hitN, -rayDir));
|
||||
if (emitterCos <= 0.0) {
|
||||
missWeight += 1.0;
|
||||
continue;
|
||||
}
|
||||
|
||||
vec3 hitAlbedo = textureLod(gbuffer1, hitUV, 0.0).rgb;
|
||||
|
||||
#ifdef _Sun
|
||||
vec4 hitG0 = textureLod(gbuffer0, hitUV, 0.0);
|
||||
vec2 hitEnc = hitG0.rg;
|
||||
vec3 hitN;
|
||||
hitN.z = 1.0 - abs(hitEnc.x) - abs(hitEnc.y);
|
||||
hitN.xy = hitN.z >= 0.0 ? hitEnc.xy : octahedronWrap(hitEnc.xy);
|
||||
hitN = normalize(hitN);
|
||||
float hitNdotL = max(0.0, dot(hitN, sunDir));
|
||||
vec3 hitRadiance = hitAlbedo * sunCol * hitNdotL;
|
||||
vec3 hitRadiance = hitAlbedo * (sunCol * hitNdotL + vec3(0.4));
|
||||
#else
|
||||
vec3 hitRadiance = hitAlbedo * 0.5;
|
||||
vec3 hitRadiance = hitAlbedo * 0.4;
|
||||
#endif
|
||||
|
||||
#ifdef _EmissionShaded
|
||||
hitRadiance += textureLod(gbufferEmission, hitUV, 0.0).rgb;
|
||||
#endif
|
||||
|
||||
gi += hitRadiance * distWeight;
|
||||
validSamples++;
|
||||
gi += hitRadiance * (distWeight * emitterCos);
|
||||
}
|
||||
|
||||
if (validSamples > 0) {
|
||||
gi /= float(validSamples);
|
||||
}
|
||||
|
||||
gi *= strength;
|
||||
gi += basecolor * 0.1 * missWeight;
|
||||
gi *= 2.0 * strength / float(ssgiSamples);
|
||||
|
||||
#ifdef _EmissionShaded
|
||||
gi += textureLod(gbufferEmission, texCoord, 0.0).rgb * 0.3;
|
||||
gi += textureLod(gbufferEmission, texCoord, 0.0).rgb * 0.3;
|
||||
#endif
|
||||
|
||||
fragColor = vec4(min(gi, vec3(2.0)), 1.0);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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));
|
||||
}
|
||||
@ -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;
|
||||
|
||||
@ -55,6 +55,8 @@ class Geometry {
|
||||
// Skinned
|
||||
#if lnx_skin
|
||||
public var skeletonTransformsI: Array<Mat4> = null;
|
||||
public var actions: Map<String, Array<iron.data.SceneFormat.TObj>> = new Map();
|
||||
public var mats: Map<String, Array<Mat4>> = new Map();
|
||||
#end
|
||||
|
||||
public function new(data: MeshData, indices: Array<Uint32Array>, materialIndices: Array<Int>, usage: Usage = null) {
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -8,7 +8,7 @@ class AlertNode extends LogicNode {
|
||||
|
||||
override function run(from: Int) {
|
||||
|
||||
#if kha_html5
|
||||
#if js
|
||||
js.Browser.window.alert(inputs[1].get());
|
||||
#end
|
||||
|
||||
|
||||
@ -2,19 +2,31 @@ package leenkx.logicnode;
|
||||
|
||||
class ConfirmNode extends LogicNode {
|
||||
|
||||
var result: Dynamic;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
|
||||
#if kha_html5
|
||||
var answer: Bool = js.Browser.window.confirm(inputs[1].get());
|
||||
if(answer)
|
||||
return runOutput(0);
|
||||
else
|
||||
return runOutput(1);
|
||||
#if js
|
||||
result = js.Browser.window.confirm(inputs[1].get());
|
||||
if (Reflect.field(result, "loaded") != null) {
|
||||
tree.notifyOnUpdate(poll);
|
||||
} else {
|
||||
if (result) runOutput(0);
|
||||
else runOutput(1);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
function poll() {
|
||||
#if js
|
||||
if (result.loaded) {
|
||||
tree.removeUpdate(poll);
|
||||
if (result.data) runOutput(0);
|
||||
else runOutput(1);
|
||||
}
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,12 +11,11 @@ class GetElementPropertyNode extends LogicNode {
|
||||
override function get(from: Int): Dynamic {
|
||||
return switch (from) {
|
||||
case 0:
|
||||
var object: Dynamic = inputs[0].get();
|
||||
var property = inputs[1].get();
|
||||
|
||||
value = Reflect.field(object, property);
|
||||
|
||||
//value = object.getAttribute(property.toString());
|
||||
#if js
|
||||
var element: Dynamic = inputs[0].get();
|
||||
var property = inputs[1].get();
|
||||
value = Reflect.field(element, property);
|
||||
#end
|
||||
default: throw "Unreachable";
|
||||
}
|
||||
}
|
||||
|
||||
16
leenkx/Sources/leenkx/logicnode/KromCopyToClipboardNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/KromCopyToClipboardNode.hx
Normal file
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromCopyToClipboardNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var text: String = inputs[1].get();
|
||||
js.Syntax.code("Krom.copyToClipboard({0})", text);
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
15
leenkx/Sources/leenkx/logicnode/KromDelayIdleSleepNode.hx
Normal file
15
leenkx/Sources/leenkx/logicnode/KromDelayIdleSleepNode.hx
Normal file
@ -0,0 +1,15 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromDelayIdleSleepNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
js.Syntax.code("Krom.delayIdleSleep()");
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
16
leenkx/Sources/leenkx/logicnode/KromDeleteFileNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/KromDeleteFileNode.hx
Normal file
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromDeleteFileNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var path: String = inputs[1].get();
|
||||
js.Syntax.code("Krom.deleteFile({0})", path);
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
17
leenkx/Sources/leenkx/logicnode/KromFileExistsNode.hx
Normal file
17
leenkx/Sources/leenkx/logicnode/KromFileExistsNode.hx
Normal file
@ -0,0 +1,17 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromFileExistsNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
var path: String = inputs[0].get();
|
||||
return js.Syntax.code("Krom.fileExists({0})", path);
|
||||
#else
|
||||
return false;
|
||||
#end
|
||||
}
|
||||
}
|
||||
16
leenkx/Sources/leenkx/logicnode/KromGetArgCountNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/KromGetArgCountNode.hx
Normal file
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromGetArgCountNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
return Krom.getArgCount();
|
||||
#else
|
||||
return 0;
|
||||
#end
|
||||
}
|
||||
}
|
||||
17
leenkx/Sources/leenkx/logicnode/KromGetArgNode.hx
Normal file
17
leenkx/Sources/leenkx/logicnode/KromGetArgNode.hx
Normal file
@ -0,0 +1,17 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromGetArgNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
var index: Int = inputs[0].get();
|
||||
return Krom.getArg(index);
|
||||
#else
|
||||
return "";
|
||||
#end
|
||||
}
|
||||
}
|
||||
16
leenkx/Sources/leenkx/logicnode/KromGetFilesLocationNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/KromGetFilesLocationNode.hx
Normal file
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromGetFilesLocationNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
return Krom.getFilesLocation();
|
||||
#else
|
||||
return "";
|
||||
#end
|
||||
}
|
||||
}
|
||||
16
leenkx/Sources/leenkx/logicnode/KromSavePathNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/KromSavePathNode.hx
Normal file
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromSavePathNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
return Krom.savePath();
|
||||
#else
|
||||
return "";
|
||||
#end
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromSetApplicationNameNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var name: String = inputs[1].get();
|
||||
js.Syntax.code("Krom.setApplicationName({0})", name);
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
16
leenkx/Sources/leenkx/logicnode/KromShowKeyboardNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/KromShowKeyboardNode.hx
Normal file
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromShowKeyboardNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var show: Bool = inputs[1].get();
|
||||
js.Syntax.code("Krom.showKeyboard({0})", show);
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
28
leenkx/Sources/leenkx/logicnode/KromSysCommandNode.hx
Normal file
28
leenkx/Sources/leenkx/logicnode/KromSysCommandNode.hx
Normal file
@ -0,0 +1,28 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class KromSysCommandNode extends LogicNode {
|
||||
|
||||
var exitCode: Int = 0;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var cmd: String = inputs[1].get();
|
||||
var args: Dynamic = inputs[2].get();
|
||||
if (args != null) {
|
||||
exitCode = Krom.sysCommand(cmd, args);
|
||||
} else {
|
||||
exitCode = Krom.sysCommand(cmd);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
if (from == 1) return exitCode;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,7 @@ class LoadUrlNode extends LogicNode {
|
||||
override function run(from: Int) {
|
||||
//System.loadUrl(inputs[1].get());
|
||||
|
||||
#if kha_html5
|
||||
#if js
|
||||
if (inputs[2].get()){
|
||||
var window = inputs[3].get() ? js.Browser.window.open(inputs[1].get(), "_blank", "width="+inputs[4].get()+",height="+inputs[5].get()+",left="+inputs[6].get()+",top="+inputs[7].get())
|
||||
: js.Browser.window.open(inputs[1].get(), "_blank");
|
||||
|
||||
@ -1,193 +0,0 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
import iron.object.Animation;
|
||||
import iron.object.Object;
|
||||
import iron.Scene;
|
||||
import kha.arrays.Float32Array;
|
||||
import iron.object.ObjectAnimation;
|
||||
|
||||
class PlayActionFromNode extends LogicNode {
|
||||
|
||||
var animation: Animation;
|
||||
var startFrame: Int;
|
||||
var endFrame: Int = -1;
|
||||
var loop: Bool;
|
||||
var reverse: Bool;
|
||||
var action: String;
|
||||
var actionR: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
tree.notifyOnUpdate(update);
|
||||
}
|
||||
|
||||
function update() {
|
||||
if (animation != null && action == animation.action) {
|
||||
if (animation.currentFrame() == endFrame-1) {
|
||||
if (loop) animation.setFrame(startFrame);
|
||||
else {
|
||||
if (!animation.paused) {
|
||||
animation.pause();
|
||||
runOutput(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
var object: Object = inputs[1].get();
|
||||
action = inputs[2].get();
|
||||
startFrame = inputs[3].get();
|
||||
endFrame = inputs[4].get();
|
||||
var blendTime: Float = inputs[5].get();
|
||||
var speed: Float = inputs[6].get();
|
||||
loop = inputs[7].get();
|
||||
reverse = inputs[8].get();
|
||||
|
||||
if (object == null) return;
|
||||
animation = object.animation;
|
||||
if (animation == null) animation = object.getParentArmature(object.name);
|
||||
|
||||
if (reverse){
|
||||
var isnew = true;
|
||||
actionR = action+'Reverse';
|
||||
|
||||
if (animation.isSkinned){
|
||||
for(a in animation.armature.actions)
|
||||
if (a.name == actionR) isnew = false;
|
||||
|
||||
if (isnew){
|
||||
for(a in animation.armature.actions)
|
||||
if(a.name == action){
|
||||
var bones = [];
|
||||
var cn = [];
|
||||
for(bone in a.bones){
|
||||
var v = bone.anim.tracks[0];
|
||||
var len: Int = v.values.length;
|
||||
var val = new Float32Array(len);
|
||||
var l = Std.int(len/16);
|
||||
for(i in 0...l)
|
||||
for(j in 0...16){
|
||||
val[i*16+j] = v.values[(l-i)*16+j-16];
|
||||
}
|
||||
|
||||
if (bone.children != null){
|
||||
var cdn = [];
|
||||
for (child in bone.children)
|
||||
cdn.push(child.name);
|
||||
cn.push(cdn);
|
||||
} else cn.push(null);
|
||||
|
||||
var a: iron.data.SceneFormat.TObj = {
|
||||
type : bone.type,
|
||||
name : bone.name,
|
||||
transform : {
|
||||
//target : null,
|
||||
values : bone.transform.values
|
||||
},
|
||||
anim : {
|
||||
tracks : [{
|
||||
target : v.target,
|
||||
frames : v.frames,
|
||||
values : val,
|
||||
ref_values : null
|
||||
}]//,
|
||||
//begin : null,
|
||||
//end : null,
|
||||
//has_delta : null,
|
||||
//marker_frames : null,
|
||||
//marker_names : null
|
||||
},
|
||||
children : bone.children,
|
||||
data_ref : null
|
||||
}
|
||||
|
||||
if (bone.parent != null){
|
||||
a.parent = bone.parent;
|
||||
}
|
||||
|
||||
bones.push(a);
|
||||
}
|
||||
|
||||
for (i in 0...bones.length){
|
||||
var cd = [];
|
||||
if (cn[i] != null)
|
||||
for (name in cn[i])
|
||||
for (bone in bones)
|
||||
if (bone.name == name)
|
||||
cd.push(bone);
|
||||
bones[i].children = cd;
|
||||
}
|
||||
|
||||
for (i in 0...bones.length){
|
||||
if (bones[i].parent != null)
|
||||
for (bone in bones)
|
||||
if (bone.name == bones[i].parent.name)
|
||||
bones[i].parent = bone;
|
||||
|
||||
}
|
||||
|
||||
animation.armature.actions.push({
|
||||
name: actionR,
|
||||
bones: bones,
|
||||
mats: null});
|
||||
|
||||
var mats: Array<iron.math.Mat4> = [];
|
||||
for (bone in a.bones) mats.push(iron.math.Mat4.fromFloat32Array(bone.transform.values));
|
||||
|
||||
var castBoneAnim = cast(animation, iron.object.BoneAnimation);
|
||||
castBoneAnim.data.geom.actions.set(actionR, bones);
|
||||
castBoneAnim.data.geom.mats.set(actionR, mats);
|
||||
|
||||
for(o in iron.Scene.active.raw.objects)
|
||||
if (o.name == object.name) o.bone_actions.push('action_'+o.bone_actions[0].split('_')[1]+'_'+actionR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
var oaction = null;
|
||||
var tracks: Array<iron.data.SceneFormat.TTrack> = [];
|
||||
|
||||
var oactions = cast(animation, ObjectAnimation).oactions;
|
||||
|
||||
for (a in oactions)
|
||||
if (a != null && a.objects[0].name == actionR) isnew = false;
|
||||
|
||||
if (isnew){
|
||||
for (a in oactions){
|
||||
if (a != null && a.objects[0].name == action){
|
||||
oaction = a.objects[0];
|
||||
for(b in a.objects[0].anim.tracks){
|
||||
var val: Array<Float> = [];
|
||||
for(c in b.values) val.unshift(c);
|
||||
var vali = new Float32Array(val.length);
|
||||
for(i in 0...val.length) vali[i] = val[i];
|
||||
tracks.push({target: b.target, frames: b.frames, values: vali});
|
||||
}
|
||||
|
||||
oactions.push({
|
||||
objects: [{name: actionR,
|
||||
anim: {begin: oaction.anim.begin, end: oaction.anim.end, tracks: tracks},
|
||||
type: 'object',
|
||||
data_ref: '',
|
||||
transform: null}]});
|
||||
|
||||
for(o in iron.Scene.active.raw.objects)
|
||||
if (o.name == object.name) o.object_actions.push('action_'+actionR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
animation.play(reverse ? actionR : action, function() {
|
||||
runOutput(1);
|
||||
}, blendTime, speed, loop);
|
||||
animation.update(startFrame * Scene.active.raw.frame_time);
|
||||
|
||||
runOutput(0);
|
||||
|
||||
}
|
||||
}
|
||||
@ -3,18 +3,32 @@ package leenkx.logicnode;
|
||||
class PromptNode extends LogicNode {
|
||||
|
||||
var input: String = null;
|
||||
var result: Dynamic;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_html5
|
||||
input = js.Browser.window.prompt(inputs[1].get(), inputs[2].get());
|
||||
|
||||
runOutput(0);
|
||||
#if js
|
||||
result = js.Browser.window.prompt(inputs[1].get(), inputs[2].get());
|
||||
if (Reflect.field(result, "loaded") != null) {
|
||||
tree.notifyOnUpdate(poll);
|
||||
} else {
|
||||
input = result;
|
||||
runOutput(0);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
function poll() {
|
||||
#if js
|
||||
if (result.loaded) {
|
||||
tree.removeUpdate(poll);
|
||||
input = result.data;
|
||||
runOutput(0);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
|
||||
@ -40,12 +40,14 @@ class RenderElementNode extends LogicNode {
|
||||
tarElem.prepend(element);
|
||||
runOutput(0);
|
||||
case "innerHTML":
|
||||
var tarElem = js.Browser.document.querySelector(selector);
|
||||
tarElem.innerHTML = element.innerHTML;
|
||||
var html: String = inputs[2].get();
|
||||
if (html == null) { return; }
|
||||
element.innerHTML = html;
|
||||
runOutput(0);
|
||||
case "innerText":
|
||||
var tarElem = js.Browser.document.querySelector(selector);
|
||||
tarElem.innerText = element.innerText;
|
||||
var html: String = inputs[2].get();
|
||||
if (html == null){ return; }
|
||||
element.innerText = html;
|
||||
runOutput(0);
|
||||
case "insertAdjacentHTML":
|
||||
var tarElem = js.Browser.document.querySelector(selector);
|
||||
|
||||
@ -12,28 +12,7 @@ class RunJavascriptNode extends LogicNode {
|
||||
#if js
|
||||
var script = inputs[1].get();
|
||||
js.Syntax.code('(1, eval)({0})', script.toString());
|
||||
|
||||
var promise:Dynamic = null;//js.Syntax.code('(1, eval)({0})', script.toString());
|
||||
if (promise != null) {
|
||||
promise.then(
|
||||
function(_) {
|
||||
//if(leenkx.network.Leenkx.data.get(element) != 'undefined'){return}
|
||||
haxe.Timer.delay(function () {
|
||||
//promiseResult(element,html);
|
||||
return;
|
||||
}, 100);
|
||||
return;
|
||||
}).then(null, function(error) {
|
||||
trace("JS SYNTAX ERROR:" + error.toString());
|
||||
haxe.Timer.delay(function () {
|
||||
//promiseResult(element,html);
|
||||
return;
|
||||
}, 100);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
runOutput(0);
|
||||
runOutput(0);
|
||||
#end
|
||||
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ class SetFirstPersonControllerNode extends LogicNode {
|
||||
}
|
||||
|
||||
override function run(from: Int): Void {
|
||||
#if lnx_physics
|
||||
// Control de las var de FirstPersonController...
|
||||
// Control FirstPersonController var
|
||||
|
||||
@ -60,6 +61,7 @@ class SetFirstPersonControllerNode extends LogicNode {
|
||||
// Alert the user if they do not have the trait assigning to the object.
|
||||
trace("ERROR: The object '" + object.name + "' does not have the FirstPersonController script assigning(assign it from (Object->add trait->bundle)).");
|
||||
}
|
||||
#end
|
||||
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ class SetOverheadPersonControllerNode extends LogicNode {
|
||||
}
|
||||
|
||||
override function run(from: Int): Void {
|
||||
#if lnx_physics
|
||||
// Control de las var de OverheadPersonController...
|
||||
// Control OverheadPersonController var
|
||||
|
||||
@ -58,6 +59,7 @@ class SetOverheadPersonControllerNode extends LogicNode {
|
||||
// Alert the user if they do not have the trait assigning to the object..
|
||||
trace("ERROR: The object '" + objectTrait.name + "' does not have the OverheadPersonController script assigning(assign it from (Object->add trait->bundle)).");
|
||||
}
|
||||
#end
|
||||
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
16
leenkx/Sources/leenkx/logicnode/WebviewCountNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/WebviewCountNode.hx
Normal file
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewCountNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
return Krom.webviewCount();
|
||||
#else
|
||||
return 0;
|
||||
#end
|
||||
}
|
||||
}
|
||||
50
leenkx/Sources/leenkx/logicnode/WebviewCreateNode.hx
Normal file
50
leenkx/Sources/leenkx/logicnode/WebviewCreateNode.hx
Normal file
@ -0,0 +1,50 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewCreateNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
var parentWindow: Int = (property0 == "embedded") ? 0 : -1;
|
||||
var x: Int = inputs[1].get();
|
||||
var y: Int = inputs[2].get();
|
||||
var width: Int = inputs[3].get();
|
||||
var height: Int = inputs[4].get();
|
||||
var transparent: Bool = inputs[5].get();
|
||||
var title: String = inputs[6].get();
|
||||
var html: String = inputs[7].get();
|
||||
var url: String = inputs[8].get();
|
||||
var show: Bool = inputs[9].get();
|
||||
|
||||
#if kha_krom
|
||||
var options: Dynamic = {
|
||||
parentWindow: parentWindow,
|
||||
x: x,
|
||||
y: y,
|
||||
width: width,
|
||||
height: height,
|
||||
transparent: transparent,
|
||||
title: title
|
||||
};
|
||||
var id: Int = Krom.webviewCreate(options);
|
||||
if (html != null && html != "") Krom.webviewLoadHTML(id, html);
|
||||
if (url != null && url != "") Krom.webviewLoadURL(id, url);
|
||||
if (show) Krom.webviewShow(id);
|
||||
#else
|
||||
var id: Int = -1;
|
||||
#end
|
||||
|
||||
this.id = id;
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
var id: Int = -1;
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
31
leenkx/Sources/leenkx/logicnode/WebviewDOMNode.hx
Normal file
31
leenkx/Sources/leenkx/logicnode/WebviewDOMNode.hx
Normal file
@ -0,0 +1,31 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewDOMNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
if (property0 == "set") {
|
||||
var id: Int = inputs[1].get();
|
||||
Krom.webviewSetActiveDOM(id);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
if (property0 == "get") {
|
||||
return Krom.webviewGetActiveDOM();
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#end
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
16
leenkx/Sources/leenkx/logicnode/WebviewDestroyNode.hx
Normal file
16
leenkx/Sources/leenkx/logicnode/WebviewDestroyNode.hx
Normal file
@ -0,0 +1,16 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewDestroyNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
Krom.webviewDestroy(id);
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
24
leenkx/Sources/leenkx/logicnode/WebviewDevSettingsNode.hx
Normal file
24
leenkx/Sources/leenkx/logicnode/WebviewDevSettingsNode.hx
Normal file
@ -0,0 +1,24 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewDevSettingsNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
var enabled: Bool = inputs[2].get();
|
||||
if (property0 == "devtools") {
|
||||
Krom.webviewEnableDevTools(id, enabled);
|
||||
}
|
||||
else {
|
||||
Krom.webviewSetContextMenu(id, enabled);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
17
leenkx/Sources/leenkx/logicnode/WebviewEvalJSNode.hx
Normal file
17
leenkx/Sources/leenkx/logicnode/WebviewEvalJSNode.hx
Normal file
@ -0,0 +1,17 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewEvalJSNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
var jsCode: String = inputs[2].get();
|
||||
Krom.webviewEvalJS(id, jsCode);
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
31
leenkx/Sources/leenkx/logicnode/WebviewFullscreenNode.hx
Normal file
31
leenkx/Sources/leenkx/logicnode/WebviewFullscreenNode.hx
Normal file
@ -0,0 +1,31 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewFullscreenNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
if (property0 == "set") {
|
||||
var id: Int = inputs[1].get();
|
||||
var fullscreen: Bool = inputs[2].get();
|
||||
Krom.webviewSetFullscreen(id, fullscreen);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
if (property0 == "get") {
|
||||
var id: Int = inputs[0].get();
|
||||
return Krom.webviewIsFullscreen(id);
|
||||
}
|
||||
#end
|
||||
return false;
|
||||
}
|
||||
}
|
||||
26
leenkx/Sources/leenkx/logicnode/WebviewGetDimensionsNode.hx
Normal file
26
leenkx/Sources/leenkx/logicnode/WebviewGetDimensionsNode.hx
Normal file
@ -0,0 +1,26 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewGetDimensionsNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[0].get();
|
||||
if (property0 == "position") {
|
||||
if (from == 0) return Krom.webviewGetX(id);
|
||||
else return Krom.webviewGetY(id);
|
||||
}
|
||||
else {
|
||||
if (from == 0) return Krom.webviewGetWidth(id);
|
||||
else return Krom.webviewGetHeight(id);
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#end
|
||||
}
|
||||
}
|
||||
17
leenkx/Sources/leenkx/logicnode/WebviewIsValidNode.hx
Normal file
17
leenkx/Sources/leenkx/logicnode/WebviewIsValidNode.hx
Normal file
@ -0,0 +1,17 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewIsValidNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[0].get();
|
||||
return Krom.webviewIsValid(id);
|
||||
#else
|
||||
return false;
|
||||
#end
|
||||
}
|
||||
}
|
||||
25
leenkx/Sources/leenkx/logicnode/WebviewLoadNode.hx
Normal file
25
leenkx/Sources/leenkx/logicnode/WebviewLoadNode.hx
Normal file
@ -0,0 +1,25 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewLoadNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
if (property0 == "html") {
|
||||
var html: String = inputs[2].get();
|
||||
Krom.webviewLoadHTML(id, html);
|
||||
}
|
||||
else {
|
||||
var url: String = inputs[2].get();
|
||||
Krom.webviewLoadURL(id, url);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
22
leenkx/Sources/leenkx/logicnode/WebviewNavigationNode.hx
Normal file
22
leenkx/Sources/leenkx/logicnode/WebviewNavigationNode.hx
Normal file
@ -0,0 +1,22 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewNavigationNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
switch (property0) {
|
||||
case "go_back": Krom.webviewGoBack(id);
|
||||
case "go_forward": Krom.webviewGoForward(id);
|
||||
case "reload": Krom.webviewReload(id);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewNavigationStateNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[0].get();
|
||||
if (property0 == "can_go_back") return Krom.webviewCanGoBack(id);
|
||||
else return Krom.webviewCanGoForward(id);
|
||||
#else
|
||||
return false;
|
||||
#end
|
||||
}
|
||||
}
|
||||
46
leenkx/Sources/leenkx/logicnode/WebviewOnEventNode.hx
Normal file
46
leenkx/Sources/leenkx/logicnode/WebviewOnEventNode.hx
Normal file
@ -0,0 +1,46 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewOnEventNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
var message: String = "";
|
||||
var error: String = "";
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[0].get();
|
||||
var self = this;
|
||||
switch (property0) {
|
||||
case "message":
|
||||
Krom.webviewSetOnMessage(id, function(msg) { self.onEvent(msg); });
|
||||
case "load":
|
||||
Krom.webviewSetOnLoad(id, function() { self.onEvent(null); });
|
||||
case "error":
|
||||
Krom.webviewSetOnError(id, function(err) { self.onEvent(err); });
|
||||
case "close":
|
||||
Krom.webviewSetOnClose(id, function() { self.onEvent(null); });
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
function onEvent(data: String) {
|
||||
if (data != null) {
|
||||
if (property0 == "message") this.message = data;
|
||||
else if (property0 == "error") this.error = data;
|
||||
}
|
||||
runOutput(0);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
if (from == 1) {
|
||||
if (property0 == "message") return message;
|
||||
if (property0 == "error") return error;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
20
leenkx/Sources/leenkx/logicnode/WebviewPageInfoNode.hx
Normal file
20
leenkx/Sources/leenkx/logicnode/WebviewPageInfoNode.hx
Normal file
@ -0,0 +1,20 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewPageInfoNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function get(from: Int): Dynamic {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[0].get();
|
||||
if (property0 == "url") return Krom.webviewGetURL(id);
|
||||
else return Krom.webviewGetPageTitle(id);
|
||||
#else
|
||||
return "";
|
||||
#end
|
||||
}
|
||||
}
|
||||
17
leenkx/Sources/leenkx/logicnode/WebviewSendNode.hx
Normal file
17
leenkx/Sources/leenkx/logicnode/WebviewSendNode.hx
Normal file
@ -0,0 +1,17 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewSendNode extends LogicNode {
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
var message: String = inputs[2].get();
|
||||
Krom.webviewSend(id, message);
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
33
leenkx/Sources/leenkx/logicnode/WebviewSetDimensionsNode.hx
Normal file
33
leenkx/Sources/leenkx/logicnode/WebviewSetDimensionsNode.hx
Normal file
@ -0,0 +1,33 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewSetDimensionsNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
switch (property0) {
|
||||
case "resize":
|
||||
var width: Int = inputs[2].get();
|
||||
var height: Int = inputs[3].get();
|
||||
Krom.webviewResize(id, width, height);
|
||||
case "move":
|
||||
var x: Int = inputs[2].get();
|
||||
var y: Int = inputs[3].get();
|
||||
Krom.webviewMove(id, x, y);
|
||||
case "set_bounds":
|
||||
var x: Int = inputs[2].get();
|
||||
var y: Int = inputs[3].get();
|
||||
var width: Int = inputs[4].get();
|
||||
var height: Int = inputs[5].get();
|
||||
Krom.webviewSetBounds(id, x, y, width, height);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
28
leenkx/Sources/leenkx/logicnode/WebviewSetPropertyNode.hx
Normal file
28
leenkx/Sources/leenkx/logicnode/WebviewSetPropertyNode.hx
Normal file
@ -0,0 +1,28 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewSetPropertyNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
switch (property0) {
|
||||
case "transparent":
|
||||
var value: Bool = inputs[2].get();
|
||||
Krom.webviewSetTransparent(id, value);
|
||||
case "click_through":
|
||||
var value: Bool = inputs[2].get();
|
||||
Krom.webviewSetClickThrough(id, value);
|
||||
case "title":
|
||||
var value: String = inputs[2].get();
|
||||
Krom.webviewSetTitle(id, value);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
23
leenkx/Sources/leenkx/logicnode/WebviewVisibilityNode.hx
Normal file
23
leenkx/Sources/leenkx/logicnode/WebviewVisibilityNode.hx
Normal file
@ -0,0 +1,23 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewVisibilityNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
if (property0 == "show") {
|
||||
Krom.webviewShow(id);
|
||||
}
|
||||
else {
|
||||
Krom.webviewHide(id);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
22
leenkx/Sources/leenkx/logicnode/WebviewWindowActionsNode.hx
Normal file
22
leenkx/Sources/leenkx/logicnode/WebviewWindowActionsNode.hx
Normal file
@ -0,0 +1,22 @@
|
||||
package leenkx.logicnode;
|
||||
|
||||
class WebviewWindowActionsNode extends LogicNode {
|
||||
|
||||
public var property0: String;
|
||||
|
||||
public function new(tree: LogicTree) {
|
||||
super(tree);
|
||||
}
|
||||
|
||||
override function run(from: Int) {
|
||||
#if kha_krom
|
||||
var id: Int = inputs[1].get();
|
||||
switch (property0) {
|
||||
case "minimize": Krom.webviewMinimize(id);
|
||||
case "maximize": Krom.webviewMaximize(id);
|
||||
case "restore": Krom.webviewRestore(id);
|
||||
}
|
||||
#end
|
||||
runOutput(0);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Clipmap>): 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -1168,7 +1187,7 @@ class RenderPathDeferred {
|
||||
|
||||
#if (rp_antialiasing == "TAA")
|
||||
#if rp_fsr1
|
||||
path.isProbe ? path.setTarget("buf") : path.setTarget("bufa");
|
||||
path.setTarget("bufa");
|
||||
#else
|
||||
path.isProbe ? path.setTarget(framebuffer) : path.setTarget("bufa");
|
||||
#end
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -93,11 +93,11 @@ class Sky {
|
||||
|
||||
var density = raw.sky_density;
|
||||
var densityVec = new Vec3(density[0], density[1], density[2]);
|
||||
var sunElevation = raw.sky_sun_elevation != null ? raw.sky_sun_elevation : 0.0;
|
||||
var sunRotation = raw.sky_sun_rotation != null ? raw.sky_sun_rotation : 0.0;
|
||||
var sunSize = raw.sky_sun_size != null ? raw.sky_sun_size : 0.545;
|
||||
var sunIntensity = raw.sky_sun_intensity != null ? raw.sky_sun_intensity : 1.0;
|
||||
var altitude = raw.sky_altitude != null ? raw.sky_altitude : 0.0;
|
||||
var sunElevation:FastFloat = raw.sky_sun_elevation != null ? raw.sky_sun_elevation : cast 0.0;
|
||||
var sunRotation:FastFloat = raw.sky_sun_rotation != null ? raw.sky_sun_rotation : cast 0.0;
|
||||
var sunSize:FastFloat = raw.sky_sun_size != null ? raw.sky_sun_size : cast 0.545;
|
||||
var sunIntensity:FastFloat = raw.sky_sun_intensity != null ? raw.sky_sun_intensity : cast 1.0;
|
||||
var altitude:FastFloat = raw.sky_altitude != null ? raw.sky_altitude : cast 0.0;
|
||||
var sunDisc = raw.sky_sun_disc != null ? raw.sky_sun_disc : 1;
|
||||
|
||||
if (!multiScatterData.needsRecompute(densityVec, sunElevation, altitude, sunSize, sunDisc != 0)) return;
|
||||
|
||||
@ -48,6 +48,21 @@ class Starter {
|
||||
mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) {
|
||||
|
||||
iron.App.init(function() {
|
||||
// TODO: Currently breaks after a second
|
||||
// TODO: Figure out why full width and height need a math operation like /2 or -1
|
||||
//#if (lnx_webview && kha_krom)
|
||||
//var wvOptions: Dynamic = {
|
||||
// parentWindow: 0,
|
||||
// x: 0,
|
||||
// y: 0,
|
||||
// width: c.window_w - 1,
|
||||
// height: c.window_h - 1,
|
||||
// transparent: true,
|
||||
// title: Main.projectName
|
||||
//};
|
||||
//var wvId: Int = Krom.webviewCreate(wvOptions);
|
||||
//Krom.webviewShow(wvId);
|
||||
//#end
|
||||
#if lnx_loadscreen
|
||||
function load(g: kha.graphics2.Graphics) {
|
||||
if (iron.Scene.active != null && iron.Scene.active.ready) iron.App.removeRender2D(load);
|
||||
@ -101,6 +116,15 @@ class Starter {
|
||||
kha.Assets.loadBlobFromPath(name, function(b: kha.Blob) {
|
||||
js.Syntax.code("(1,eval)({0})", b.toString());
|
||||
#if kha_krom
|
||||
#if lnx_jolt_mt
|
||||
js.Syntax.code("Jolt({print:function(s){iron.log(s);},instantiateWasm:function(imports,successCallback) {
|
||||
var wasmbin = Krom.loadBlob('jolt.mt.wasm.wasm');
|
||||
var module = new WebAssembly.Module(wasmbin);
|
||||
var inst = new WebAssembly.Instance(module,imports);
|
||||
successCallback(inst,module);
|
||||
return inst.exports;
|
||||
}}).then(function(m){ Jolt=m; tasks--; start();})");
|
||||
#else
|
||||
js.Syntax.code("Jolt({print:function(s){iron.log(s);},instantiateWasm:function(imports,successCallback) {
|
||||
var wasmbin = Krom.loadBlob('jolt.wasm.wasm');
|
||||
var module = new WebAssembly.Module(wasmbin);
|
||||
@ -108,6 +132,7 @@ class Starter {
|
||||
successCallback(inst);
|
||||
return inst.exports;
|
||||
}}).then(function(m){ Jolt=m; tasks--; start();})");
|
||||
#end
|
||||
#else
|
||||
js.Syntax.code("Jolt({print:function(s){iron.log(s);},locateFile:function(f){return 'jolt.wasm.wasm';}}).then(function(m){ Jolt=m; tasks--; start();})");
|
||||
#end
|
||||
@ -147,8 +172,12 @@ class Starter {
|
||||
|
||||
#if (js && lnx_jolt)
|
||||
tasks++;
|
||||
#if lnx_jolt_mt
|
||||
loadLibJolt("jolt.mt.wasm.js");
|
||||
#else
|
||||
loadLibJolt("jolt.wasm.js");
|
||||
#end
|
||||
#end
|
||||
|
||||
#if (js && lnx_navigation)
|
||||
tasks++;
|
||||
|
||||
@ -6,14 +6,14 @@ import iron.Trait;
|
||||
import iron.object.MeshObject;
|
||||
import iron.data.MeshData;
|
||||
import iron.data.SceneFormat;
|
||||
#if (lnx_bullet || lnx_oimo)
|
||||
#if lnx_physics
|
||||
import leenkx.trait.physics.RigidBody;
|
||||
import leenkx.trait.physics.PhysicsWorld;
|
||||
#end
|
||||
|
||||
class PhysicsBreak extends Trait {
|
||||
|
||||
#if (!lnx_bullet && !lnx_oimo)
|
||||
#if (!lnx_physics)
|
||||
public function new() { super(); }
|
||||
#else
|
||||
|
||||
@ -74,14 +74,16 @@ class PhysicsBreak extends Trait {
|
||||
impactNormal = p.normOnB;
|
||||
#elseif lnx_oimo
|
||||
impactNormal = p.nor;
|
||||
#else
|
||||
impactNormal = p.normOnB;
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
#if lnx_bullet
|
||||
var fractureImpulse = 4.0;
|
||||
#elseif lnx_oimo
|
||||
#if lnx_oimo
|
||||
var fractureImpulse = 1.0;
|
||||
#else
|
||||
var fractureImpulse = 4.0;
|
||||
#end
|
||||
if (maxImpulse > fractureImpulse && impactPoint != null && impactNormal != null) {
|
||||
var radialIter = 1;
|
||||
|
||||
@ -11,25 +11,38 @@ import leenkx.trait.physics.PhysicsWorld;
|
||||
|
||||
class PhysicsDrag extends Trait {
|
||||
|
||||
#if (!lnx_bullet)
|
||||
#if (!lnx_physics)
|
||||
public function new() { super(); }
|
||||
#else
|
||||
|
||||
#if lnx_bullet
|
||||
@prop public var linearLowerLimit = new Vec3(0,0,0);
|
||||
@prop public var linearUpperLimit = new Vec3(0,0,0);
|
||||
@prop public var angularLowerLimit = new Vec3(-10,-10,-10);
|
||||
@prop public var angularUpperLimit = new Vec3(10,10,10);
|
||||
|
||||
var pickConstraint: bullet.Bt.Generic6DofConstraint = null;
|
||||
var pickDist: Float;
|
||||
var pickedBody: RigidBody = null;
|
||||
|
||||
var rayFrom: bullet.Bt.Vector3;
|
||||
var rayTo: bullet.Bt.Vector3;
|
||||
#end
|
||||
#if lnx_jolt
|
||||
var pickConstraint:jolt.Jt.TwoBodyConstraint = null;
|
||||
var anchorBody:jolt.Jt.Body = null;
|
||||
var anchorBodyId:jolt.Jt.BodyID = null;
|
||||
var localPivot:Vec4 = null;
|
||||
#end
|
||||
|
||||
var pickDist:Float;
|
||||
var pickedBody:RigidBody = null;
|
||||
|
||||
static var v = new Vec4();
|
||||
static var m = Mat4.identity();
|
||||
static var first = true;
|
||||
static var start = new Vec4();
|
||||
static var end = new Vec4();
|
||||
#if lnx_jolt
|
||||
static var anchorPos:jolt.Jt.RVec3 = null;
|
||||
static var anchorRot:jolt.Jt.Quat = null;
|
||||
#end
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
@ -45,81 +58,135 @@ class PhysicsDrag extends Trait {
|
||||
|
||||
var mouse = Input.getMouse();
|
||||
if (mouse.started()) {
|
||||
|
||||
var b = physics.pickClosest(mouse.x, mouse.y);
|
||||
if (b != null && b.mass > 0 && !b.body.isKinematicObject() && b.object.getTrait(PhysicsDrag) != null) {
|
||||
|
||||
setRays();
|
||||
if (b != null && b.mass > 0 && isDraggable(b) && b.object.getTrait(PhysicsDrag) != null) {
|
||||
pickedBody = b;
|
||||
|
||||
m.getInverse(b.object.transform.world);
|
||||
var hit = physics.hitPointWorld;
|
||||
var camera = iron.Scene.active.camera;
|
||||
var camLoc = camera.transform.world.getLoc();
|
||||
pickDist = v.set(hit.x - camLoc.x, hit.y - camLoc.y, hit.z - camLoc.z).length();
|
||||
|
||||
#if lnx_bullet
|
||||
setRays();
|
||||
m.getInverse(b.object.transform.world);
|
||||
v.setFrom(hit);
|
||||
v.applymat4(m);
|
||||
var localPivot = new bullet.Bt.Vector3(v.x, v.y, v.z);
|
||||
var tr = new bullet.Bt.Transform();
|
||||
tr.setIdentity();
|
||||
tr.setOrigin(localPivot);
|
||||
|
||||
pickConstraint = new bullet.Bt.Generic6DofConstraint(b.body, tr, false);
|
||||
pickConstraint.setLinearLowerLimit(new bullet.Bt.Vector3(linearLowerLimit.x, linearLowerLimit.y, linearLowerLimit.z));
|
||||
pickConstraint.setLinearUpperLimit(new bullet.Bt.Vector3(linearUpperLimit.x, linearUpperLimit.y, linearUpperLimit.z));
|
||||
pickConstraint.setAngularLowerLimit(new bullet.Bt.Vector3(angularLowerLimit.x, angularLowerLimit.y, angularLowerLimit.z));
|
||||
pickConstraint.setAngularUpperLimit(new bullet.Bt.Vector3(angularUpperLimit.x, angularUpperLimit.y, angularUpperLimit.z));
|
||||
physics.world.addConstraint(pickConstraint, false);
|
||||
#elseif lnx_jolt
|
||||
// Compute local pivot on the body (world hit -> body local)
|
||||
m.getInverse(b.object.transform.world);
|
||||
localPivot = new Vec4();
|
||||
localPivot.setFrom(hit);
|
||||
localPivot.applymat4(m);
|
||||
|
||||
/*pickConstraint.setParam(4, 0.8, 0);
|
||||
pickConstraint.setParam(4, 0.8, 1);
|
||||
pickConstraint.setParam(4, 0.8, 2);
|
||||
pickConstraint.setParam(4, 0.8, 3);
|
||||
pickConstraint.setParam(4, 0.8, 4);
|
||||
pickConstraint.setParam(4, 0.8, 5);
|
||||
// Create a small kinematic anchor body at the hit point
|
||||
var aPos = new jolt.Jt.RVec3(hit.x, hit.y, hit.z);
|
||||
var aRot = new jolt.Jt.Quat(0, 0, 0, 1);
|
||||
var anchorShape = new jolt.Jt.SphereShape(0.01);
|
||||
var anchorSettings = new jolt.Jt.BodyCreationSettings(anchorShape, aPos, aRot, jolt.Jt.EMotionType.Kinematic, 0);
|
||||
anchorSettings.mGravityFactor = 0.0;
|
||||
anchorBody = physics.bodyInterface.CreateBody(anchorSettings);
|
||||
anchorBodyId = anchorBody.GetID();
|
||||
physics.bodyInterface.AddBody(anchorBodyId, jolt.Jt.EActivation.Activate);
|
||||
#if hl anchorSettings.delete(); aPos.delete(); aRot.delete(); #end
|
||||
|
||||
pickConstraint.setParam(1, 0.1, 0);
|
||||
pickConstraint.setParam(1, 0.1, 1);
|
||||
pickConstraint.setParam(1, 0.1, 2);
|
||||
pickConstraint.setParam(1, 0.1, 3);
|
||||
pickConstraint.setParam(1, 0.1, 4);
|
||||
pickConstraint.setParam(1, 0.1, 5);*/
|
||||
|
||||
pickDist = v.set(hit.x - rayFrom.x(), hit.y - rayFrom.y(), hit.z - rayFrom.z()).length();
|
||||
// Create SixDOFConstraint: translation locked, rotation free
|
||||
var sixDof = new jolt.Jt.SixDOFConstraintSettings();
|
||||
sixDof.mSpace = 0; // LocalToBodyCOM
|
||||
var p1 = new jolt.Jt.RVec3(localPivot.x, localPivot.y, localPivot.z);
|
||||
var p2 = new jolt.Jt.RVec3(0, 0, 0);
|
||||
var ax1 = new jolt.Jt.Vec3(1, 0, 0);
|
||||
var ay1 = new jolt.Jt.Vec3(0, 1, 0);
|
||||
var ax2 = new jolt.Jt.Vec3(1, 0, 0);
|
||||
var ay2 = new jolt.Jt.Vec3(0, 1, 0);
|
||||
sixDof.mPosition1 = p1;
|
||||
sixDof.mPosition2 = p2;
|
||||
sixDof.mAxisX1 = ax1;
|
||||
sixDof.mAxisY1 = ay1;
|
||||
sixDof.mAxisX2 = ax2;
|
||||
sixDof.mAxisY2 = ay2;
|
||||
sixDof.MakeFixedAxis(0);
|
||||
sixDof.MakeFixedAxis(1);
|
||||
sixDof.MakeFixedAxis(2);
|
||||
sixDof.MakeFreeAxis(3);
|
||||
sixDof.MakeFreeAxis(4);
|
||||
sixDof.MakeFreeAxis(5);
|
||||
pickConstraint = sixDof.Create(b.body, anchorBody);
|
||||
physics.physicsSystem.AddConstraint(pickConstraint);
|
||||
#if hl sixDof.delete(); p1.delete(); p2.delete(); ax1.delete(); ay1.delete(); ax2.delete(); ay2.delete(); #end
|
||||
#end
|
||||
|
||||
Input.occupied = true;
|
||||
}
|
||||
}
|
||||
|
||||
else if (mouse.released()) {
|
||||
#if lnx_bullet
|
||||
if (pickConstraint != null) {
|
||||
physics.world.removeConstraint(pickConstraint);
|
||||
pickConstraint = null;
|
||||
pickedBody = null;
|
||||
}
|
||||
#elseif lnx_jolt
|
||||
if (pickConstraint != null) {
|
||||
physics.physicsSystem.RemoveConstraint(pickConstraint);
|
||||
pickConstraint = null;
|
||||
}
|
||||
if (anchorBodyId != null) {
|
||||
physics.bodyInterface.RemoveBody(anchorBodyId);
|
||||
physics.bodyInterface.DestroyBody(anchorBodyId);
|
||||
anchorBodyId = null;
|
||||
anchorBody = null;
|
||||
}
|
||||
localPivot = null;
|
||||
#end
|
||||
pickedBody = null;
|
||||
Input.occupied = false;
|
||||
}
|
||||
|
||||
else if (mouse.down()) {
|
||||
if (pickConstraint != null) {
|
||||
setRays();
|
||||
|
||||
// Keep it at the same picking distance
|
||||
var dir = new bullet.Bt.Vector3(rayTo.x() - rayFrom.x(), rayTo.y() - rayFrom.y(), rayTo.z() - rayFrom.z());
|
||||
dir.normalize();
|
||||
dir.setX(dir.x() * pickDist);
|
||||
dir.setY(dir.y() * pickDist);
|
||||
dir.setZ(dir.z() * pickDist);
|
||||
var newPivotB = new bullet.Bt.Vector3(rayFrom.x() + dir.x(), rayFrom.y() + dir.y(), rayFrom.z() + dir.z());
|
||||
|
||||
#if (js || hl)
|
||||
pickConstraint.getFrameOffsetA().setOrigin(newPivotB);
|
||||
#elseif cpp
|
||||
pickConstraint.setFrameOffsetAOrigin(newPivotB);
|
||||
if (pickedBody != null) {
|
||||
#if lnx_bullet
|
||||
if (pickConstraint != null) {
|
||||
setRays();
|
||||
var dir = new bullet.Bt.Vector3(rayTo.x() - rayFrom.x(), rayTo.y() - rayFrom.y(), rayTo.z() - rayFrom.z());
|
||||
dir.normalize();
|
||||
dir.setX(dir.x() * pickDist);
|
||||
dir.setY(dir.y() * pickDist);
|
||||
dir.setZ(dir.z() * pickDist);
|
||||
var newPivotB = new bullet.Bt.Vector3(rayFrom.x() + dir.x(), rayFrom.y() + dir.y(), rayFrom.z() + dir.z());
|
||||
#if (js || hl)
|
||||
pickConstraint.getFrameOffsetA().setOrigin(newPivotB);
|
||||
#elseif cpp
|
||||
pickConstraint.setFrameOffsetAOrigin(newPivotB);
|
||||
#end
|
||||
}
|
||||
#elseif lnx_jolt
|
||||
if (pickConstraint != null) {
|
||||
setAnchorTarget(physics);
|
||||
}
|
||||
#end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static var start = new Vec4();
|
||||
static var end = new Vec4();
|
||||
inline function isDraggable(b:RigidBody):Bool {
|
||||
#if lnx_bullet
|
||||
return !b.body.isKinematicObject();
|
||||
#elseif lnx_jolt
|
||||
return !b.staticObj && !b.animated;
|
||||
#else
|
||||
return true;
|
||||
#end
|
||||
}
|
||||
|
||||
#if lnx_bullet
|
||||
inline function setRays() {
|
||||
var mouse = Input.getMouse();
|
||||
var camera = iron.Scene.active.camera;
|
||||
@ -128,5 +195,37 @@ class PhysicsDrag extends Trait {
|
||||
RayCaster.getDirection(start, end, mouse.x, mouse.y, camera);
|
||||
rayTo = new bullet.Bt.Vector3(end.x, end.y, end.z);
|
||||
}
|
||||
#end
|
||||
|
||||
#if lnx_jolt
|
||||
inline function setAnchorTarget(physics:PhysicsWorld) {
|
||||
var mouse = Input.getMouse();
|
||||
var camera = iron.Scene.active.camera;
|
||||
var camLoc = camera.transform.world.getLoc();
|
||||
RayCaster.getDirection(start, end, mouse.x, mouse.y, camera);
|
||||
var dirX = end.x - camLoc.x;
|
||||
var dirY = end.y - camLoc.y;
|
||||
var dirZ = end.z - camLoc.z;
|
||||
var len = Math.sqrt(dirX * dirX + dirY * dirY + dirZ * dirZ);
|
||||
if (len > 0) { dirX /= len; dirY /= len; dirZ /= len; }
|
||||
var targetX = camLoc.x + dirX * pickDist;
|
||||
var targetY = camLoc.y + dirY * pickDist;
|
||||
var targetZ = camLoc.z + dirZ * pickDist;
|
||||
|
||||
var t = iron.system.Time.fixedStep;
|
||||
#if hl
|
||||
RigidBody.hlPos.Set(targetX, targetY, targetZ);
|
||||
physics.bodyInterface.MoveKinematic(anchorBodyId, RigidBody.hlPos, RigidBody.hlRot, t);
|
||||
#else
|
||||
if (anchorPos == null) {
|
||||
anchorPos = new jolt.Jt.RVec3(0, 0, 0);
|
||||
anchorRot = new jolt.Jt.Quat(0, 0, 0, 1);
|
||||
}
|
||||
anchorPos.Set(targetX, targetY, targetZ);
|
||||
physics.bodyInterface.MoveKinematic(anchorBodyId, anchorPos, anchorRot, t);
|
||||
#end
|
||||
}
|
||||
#end
|
||||
|
||||
#end
|
||||
}
|
||||
|
||||
@ -7,12 +7,17 @@ import iron.object.Transform;
|
||||
import iron.system.Time;
|
||||
import leenkx.trait.physics.PhysicsWorld;
|
||||
|
||||
class VehicleBody extends Trait {
|
||||
#if (!lnx_physics)
|
||||
|
||||
class VehicleBody extends Trait { public function new() { super(); } }
|
||||
class VehicleWheel { public function new() {} }
|
||||
|
||||
#if (!lnx_bullet)
|
||||
public function new() { super(); }
|
||||
#else
|
||||
|
||||
#if lnx_bullet
|
||||
|
||||
class VehicleBody extends Trait {
|
||||
|
||||
@prop var wheel0Name: String = "Wheel0";
|
||||
@prop var wheel1Name: String = "Wheel1";
|
||||
@prop var wheel2Name: String = "Wheel2";
|
||||
@ -232,34 +237,44 @@ class VehicleBody extends Trait {
|
||||
static inline var keyStrafeUp = "e";
|
||||
static inline var keyStrafeDown = "q";
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
class VehicleWheel {
|
||||
|
||||
#if (!lnx_bullet)
|
||||
public function new() {}
|
||||
#else
|
||||
public var isFrontWheel: Bool;
|
||||
public var wheelRadius: Float;
|
||||
public var wheelWidth: Float;
|
||||
|
||||
public var isFrontWheel: Bool;
|
||||
public var wheelRadius: Float;
|
||||
public var wheelWidth: Float;
|
||||
var locX: Float;
|
||||
var locY: Float;
|
||||
var locZ: Float;
|
||||
|
||||
var locX: Float;
|
||||
var locY: Float;
|
||||
var locZ: Float;
|
||||
public function new(id: Int, transform: Transform, vehicleTransform: Transform) {
|
||||
wheelRadius = transform.dim.z / 2;
|
||||
wheelWidth = transform.dim.x > transform.dim.y ? transform.dim.y : transform.dim.x;
|
||||
|
||||
public function new(id: Int, transform: Transform, vehicleTransform: Transform) {
|
||||
wheelRadius = transform.dim.z / 2;
|
||||
wheelWidth = transform.dim.x > transform.dim.y ? transform.dim.y : transform.dim.x;
|
||||
locX = transform.loc.x;
|
||||
locY = transform.loc.y;
|
||||
locZ = vehicleTransform.dim.z / 2 + transform.loc.z;
|
||||
}
|
||||
|
||||
locX = transform.loc.x;
|
||||
locY = transform.loc.y;
|
||||
locZ = vehicleTransform.dim.z / 2 + transform.loc.z;
|
||||
public function getConnectionPoint(): bullet.Bt.Vector3 {
|
||||
return new bullet.Bt.Vector3(locX, locY, locZ);
|
||||
}
|
||||
}
|
||||
|
||||
public function getConnectionPoint(): bullet.Bt.Vector3 {
|
||||
return new bullet.Bt.Vector3(locX, locY, locZ);
|
||||
}
|
||||
#end
|
||||
|
||||
#elseif lnx_jolt
|
||||
|
||||
typedef VehicleBody = leenkx.trait.physics.jolt.VehicleBody;
|
||||
typedef VehicleWheel = leenkx.trait.physics.jolt.VehicleWheel;
|
||||
|
||||
#else
|
||||
|
||||
class VehicleBody extends Trait { public function new() { super(); } }
|
||||
class VehicleWheel { public function new() {} }
|
||||
|
||||
#end
|
||||
|
||||
#end
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ class LivePatch extends iron.Trait {
|
||||
var id = Std.parseInt(lines[0]);
|
||||
if (id > patchId) {
|
||||
patchId = id;
|
||||
js.Lib.eval(lines[1]);
|
||||
js.Syntax.code("var iron = {0}, LivePatch = {1}; eval({2})", Bridge, LivePatch, lines[1]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import iron.math.Quat;
|
||||
import iron.math.Mat4;
|
||||
import iron.object.Object;
|
||||
|
||||
@:enum abstract ConstraintType(Int) from Int to Int {
|
||||
enum abstract ConstraintType(Int) from Int to Int {
|
||||
var Fixed = 0;
|
||||
var Point = 1;
|
||||
var Hinge = 2;
|
||||
@ -396,7 +396,7 @@ class PhysicsConstraint extends Trait {
|
||||
}
|
||||
}
|
||||
|
||||
@:enum abstract ConstraintAxis(Int) from Int to Int {
|
||||
enum abstract ConstraintAxis(Int) from Int to Int {
|
||||
var X = 0;
|
||||
var Y = 1;
|
||||
var Z = 2;
|
||||
|
||||
@ -59,6 +59,7 @@ class PhysicsWorld extends Trait {
|
||||
var contacts:Array<ContactPair>;
|
||||
var preUpdates:Array<Void->Void> = null;
|
||||
public var rbMap:Map<Int, RigidBody>;
|
||||
public var bodyIdMap:Map<Int, RigidBody>;
|
||||
public var conMap:Map<Int, PhysicsConstraint>;
|
||||
public var constraints:Array<PhysicsConstraint> = [];
|
||||
public var timeScale = 1.0;
|
||||
@ -77,6 +78,21 @@ class PhysicsWorld extends Trait {
|
||||
static var vec2:jolt.Jt.Vec3 = null;
|
||||
static var quat1:jolt.Jt.Quat = null;
|
||||
|
||||
// Cached raycast objects
|
||||
static var rayOrigin:jolt.Jt.RVec3 = null;
|
||||
static var rayDir:jolt.Jt.Vec3 = null;
|
||||
static var cachedRay:jolt.Jt.RRayCast = null;
|
||||
static var rayResult:jolt.Jt.RayCastResult = null;
|
||||
static var raySettings:jolt.Jt.RayCastSettings = null;
|
||||
#if js
|
||||
static var rayCollector:jolt.Jt.CastRayClosestHitCollisionCollector = null;
|
||||
#end
|
||||
static var bpFilter:jolt.Jt.BroadPhaseLayerFilter = null;
|
||||
static var objFilter:jolt.Jt.ObjectLayerFilter = null;
|
||||
static var bodyFilter:jolt.Jt.BodyFilter = null;
|
||||
static var shapeFilter:jolt.Jt.ShapeFilter = null;
|
||||
static var narrowPhaseQuery:jolt.Jt.NarrowPhaseQuery = null;
|
||||
|
||||
#if js
|
||||
var joltInterface:jolt.Jt.JoltInterface;
|
||||
static var joltReady = false;
|
||||
@ -110,6 +126,7 @@ class PhysicsWorld extends Trait {
|
||||
|
||||
contacts = [];
|
||||
rbMap = new Map();
|
||||
bodyIdMap = new Map();
|
||||
conMap = new Map();
|
||||
active = this;
|
||||
|
||||
@ -157,6 +174,7 @@ class PhysicsWorld extends Trait {
|
||||
#if hl
|
||||
// Must initialize Jolt allocator before ANY Jolt object creation
|
||||
hlJoltInit();
|
||||
RigidBody.hlInitVars();
|
||||
#end
|
||||
|
||||
if (nullvec) {
|
||||
@ -164,6 +182,21 @@ class PhysicsWorld extends Trait {
|
||||
vec1 = new jolt.Jt.Vec3(0, 0, 0);
|
||||
vec2 = new jolt.Jt.Vec3(0, 0, 0);
|
||||
quat1 = new jolt.Jt.Quat(0, 0, 0, 1);
|
||||
rayOrigin = new jolt.Jt.RVec3(0, 0, 0);
|
||||
rayDir = new jolt.Jt.Vec3(0, 0, 0);
|
||||
cachedRay = new jolt.Jt.RRayCast(rayOrigin, rayDir);
|
||||
rayResult = new jolt.Jt.RayCastResult();
|
||||
raySettings = new jolt.Jt.RayCastSettings();
|
||||
#if js
|
||||
rayCollector = new jolt.Jt.CastRayClosestHitCollisionCollector();
|
||||
#end
|
||||
bpFilter = new jolt.Jt.BroadPhaseLayerFilter();
|
||||
#if hl
|
||||
objFilter = new jolt.Jt.ObjectLayerFilter();
|
||||
#end
|
||||
bodyFilter = new jolt.Jt.BodyFilter();
|
||||
shapeFilter = new jolt.Jt.ShapeFilter();
|
||||
narrowPhaseQuery = null;
|
||||
}
|
||||
|
||||
if (!physicsReady) {
|
||||
@ -220,6 +253,10 @@ class PhysicsWorld extends Trait {
|
||||
joltInterface = new jolt.Jt.JoltInterface(settings);
|
||||
physicsSystem = joltInterface.GetPhysicsSystem();
|
||||
bodyInterface = physicsSystem.GetBodyInterface();
|
||||
|
||||
if (objFilter == null) {
|
||||
objFilter = new jolt.Jt.DefaultObjectLayerFilter(objectLayerPair, 0);
|
||||
}
|
||||
#end
|
||||
|
||||
physicsReady = true;
|
||||
@ -243,8 +280,9 @@ class PhysicsWorld extends Trait {
|
||||
}
|
||||
|
||||
public function addRigidBody(body:RigidBody, activate:Bool = true) {
|
||||
bodyInterface.AddBody(body.bodyId, activate ? 1 : 0);
|
||||
bodyInterface.AddBody(body.bodyId, activate ? 0 : 1);
|
||||
rbMap.set(body.id, body);
|
||||
bodyIdMap.set(body.bodyId.GetIndex(), body);
|
||||
}
|
||||
|
||||
public function addPhysicsConstraint(constraint:PhysicsConstraint) {
|
||||
@ -262,6 +300,7 @@ class PhysicsWorld extends Trait {
|
||||
bodyInterface.RemoveBody(body.bodyId);
|
||||
bodyInterface.DestroyBody(body.bodyId);
|
||||
rbMap.remove(body.id);
|
||||
bodyIdMap.remove(body.bodyId.GetIndex());
|
||||
}
|
||||
|
||||
public function removePhysicsConstraint(constraint:PhysicsConstraint) {
|
||||
@ -354,41 +393,39 @@ class PhysicsWorld extends Trait {
|
||||
var dirY = to.y - from.y;
|
||||
var dirZ = to.z - from.z;
|
||||
|
||||
var origin = new jolt.Jt.RVec3(from.x, from.y, from.z);
|
||||
var direction = new jolt.Jt.Vec3(dirX, dirY, dirZ);
|
||||
var ray = new jolt.Jt.RRayCast(origin, direction);
|
||||
var result = new jolt.Jt.RayCastResult();
|
||||
|
||||
var narrowPhase = physicsSystem.GetNarrowPhaseQuery();
|
||||
var didHit = narrowPhase.CastRay(ray, result);
|
||||
// reuse cached objects
|
||||
rayOrigin.Set(from.x, from.y, from.z);
|
||||
rayDir.Set(dirX, dirY, dirZ);
|
||||
cachedRay.mOrigin = rayOrigin;
|
||||
cachedRay.mDirection = rayDir;
|
||||
|
||||
if (narrowPhaseQuery == null){
|
||||
narrowPhaseQuery = physicsSystem.GetNarrowPhaseQuery();
|
||||
}
|
||||
rayResult.mFraction = 1.0;
|
||||
#if hl
|
||||
var didHit = narrowPhaseQuery.CastRay(cachedRay, rayResult, raySettings, bpFilter, objFilter, bodyFilter, shapeFilter);
|
||||
#else
|
||||
rayCollector.Reset();
|
||||
narrowPhaseQuery.CastRay(cachedRay, raySettings, rayCollector, bpFilter, objFilter, bodyFilter, shapeFilter);
|
||||
var didHit = rayCollector.HadHit();
|
||||
if (didHit) {
|
||||
var bodyId = result.mBodyID;
|
||||
var fraction = result.mFraction;
|
||||
var hit = rayCollector.mHit;
|
||||
rayResult.mBodyID = hit.mBodyID;
|
||||
rayResult.mFraction = hit.mFraction;
|
||||
}
|
||||
#end
|
||||
var fraction = rayResult.mFraction;
|
||||
|
||||
if (didHit && fraction < 1.0) {
|
||||
var bodyId = rayResult.mBodyID;
|
||||
hitPointWorld.set(from.x + dirX * fraction, from.y + dirY * fraction, from.z + dirZ * fraction);
|
||||
|
||||
// Find rigid body by ID
|
||||
for (rb in rbMap) {
|
||||
if (rb.bodyId.GetIndex() == bodyId.GetIndex()) {
|
||||
#if hl
|
||||
origin.delete();
|
||||
direction.delete();
|
||||
ray.delete();
|
||||
result.delete();
|
||||
#end
|
||||
return new Hit(rb, hitPointWorld.clone(), hitNormalWorld.clone());
|
||||
}
|
||||
var rb = bodyIdMap.get(bodyId.GetIndex());
|
||||
if (rb != null) {
|
||||
return new Hit(rb, hitPointWorld.clone(), hitNormalWorld.clone());
|
||||
}
|
||||
}
|
||||
|
||||
#if hl
|
||||
origin.delete();
|
||||
direction.delete();
|
||||
ray.delete();
|
||||
result.delete();
|
||||
#end
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ import iron.data.SceneFormat;
|
||||
import iron.object.Transform;
|
||||
import iron.object.MeshObject;
|
||||
|
||||
@:enum abstract Shape(Int) from Int to Int {
|
||||
enum abstract Shape(Int) from Int to Int {
|
||||
var Box = 0;
|
||||
var Sphere = 1;
|
||||
var ConvexHull = 2;
|
||||
@ -410,14 +410,14 @@ class RigidBody extends Trait {
|
||||
var scalePos = mo.data.scalePos;
|
||||
var numVerts = Std.int(positions.length / 4);
|
||||
|
||||
var settings:Dynamic = untyped __js__("new Jolt.ConvexHullShapeSettings()");
|
||||
var settings:Dynamic = new jolt.Jt.ConvexHullShapeSettings();
|
||||
var points:Dynamic = untyped settings.mPoints;
|
||||
points.clear();
|
||||
for (i in 0...numVerts) {
|
||||
var x:Float = (positions[i * 4] / 32767) * scalePos * scale.x;
|
||||
var y:Float = (positions[i * 4 + 1] / 32767) * scalePos * scale.y;
|
||||
var z:Float = (positions[i * 4 + 2] / 32767) * scalePos * scale.z;
|
||||
var pt:Dynamic = untyped __js__("new Jolt.Vec3({0}, {1}, {2})", x, y, z);
|
||||
var pt:Dynamic = new jolt.Jt.Vec3(x, y, z);
|
||||
untyped points.push_back(pt);
|
||||
}
|
||||
|
||||
@ -439,7 +439,7 @@ class RigidBody extends Trait {
|
||||
var scalePos = mo.data.scalePos;
|
||||
var numVerts = Std.int(positions.length / 4);
|
||||
|
||||
var settings:Dynamic = untyped __js__("new Jolt.MeshShapeSettings()");
|
||||
var settings:Dynamic = new jolt.Jt.MeshShapeSettings();
|
||||
var verts:Dynamic = untyped settings.mTriangleVertices;
|
||||
var tris:Dynamic = untyped settings.mIndexedTriangles;
|
||||
verts.clear();
|
||||
@ -449,14 +449,14 @@ class RigidBody extends Trait {
|
||||
var x:Float = (positions[i * 4] / 32767) * scalePos * scale.x;
|
||||
var y:Float = (positions[i * 4 + 1] / 32767) * scalePos * scale.y;
|
||||
var z:Float = (positions[i * 4 + 2] / 32767) * scalePos * scale.z;
|
||||
var v:Dynamic = untyped __js__("new Jolt.Float3({0}, {1}, {2})", x, y, z);
|
||||
var v:Dynamic = new jolt.Jt.Float3(x, y, z);
|
||||
untyped verts.push_back(v);
|
||||
}
|
||||
|
||||
for (indexArray in indices) {
|
||||
var numTris = Std.int(indexArray.length / 3);
|
||||
for (i in 0...numTris) {
|
||||
var tri:Dynamic = untyped __js__("new Jolt.IndexedTriangle()");
|
||||
var tri:Dynamic = new jolt.Jt.IndexedTriangle();
|
||||
untyped tri.set_mIdx(0, indexArray[i * 3]);
|
||||
untyped tri.set_mIdx(1, indexArray[i * 3 + 1]);
|
||||
untyped tri.set_mIdx(2, indexArray[i * 3 + 2]);
|
||||
@ -482,6 +482,25 @@ class RigidBody extends Trait {
|
||||
var currentRotZ:Float = 0;
|
||||
var currentRotW:Float = 1;
|
||||
|
||||
#if hl
|
||||
public static var hlPos:jolt.Jt.RVec3 = null;
|
||||
public static var hlRot:jolt.Jt.Quat = null;
|
||||
public static var hlVel:jolt.Jt.Vec3 = null;
|
||||
public static var hlForce:jolt.Jt.Vec3 = null;
|
||||
public static var hlPosR:jolt.Jt.RVec3 = null;
|
||||
public static var hlQuat:jolt.Jt.Quat = null;
|
||||
|
||||
public static function hlInitVars() {
|
||||
if (hlPos != null) return;
|
||||
hlPos = new jolt.Jt.RVec3(0, 0, 0);
|
||||
hlRot = new jolt.Jt.Quat(0, 0, 0, 1);
|
||||
hlVel = new jolt.Jt.Vec3(0, 0, 0);
|
||||
hlForce = new jolt.Jt.Vec3(0, 0, 0);
|
||||
hlPosR = new jolt.Jt.RVec3(0, 0, 0);
|
||||
hlQuat = new jolt.Jt.Quat(0, 0, 0, 1);
|
||||
}
|
||||
#end
|
||||
|
||||
public function physicsUpdate() {
|
||||
if (!ready)
|
||||
return;
|
||||
@ -494,18 +513,26 @@ class RigidBody extends Trait {
|
||||
return;
|
||||
}
|
||||
|
||||
var active = physics.bodyInterface.IsActive(bodyId);
|
||||
if (!active) {
|
||||
// Activate body if sleeping
|
||||
physics.bodyInterface.ActivateBody(bodyId);
|
||||
#if hl
|
||||
if (!body.IsActive())
|
||||
return;
|
||||
}
|
||||
|
||||
// Read position and rotation from Jolt into cached state
|
||||
body.GetPositionInto(hlPos);
|
||||
body.GetRotationInto(hlRot);
|
||||
currentPosX = hlPos.GetX();
|
||||
currentPosY = hlPos.GetY();
|
||||
currentPosZ = hlPos.GetZ();
|
||||
currentRotX = hlRot.GetX();
|
||||
currentRotY = hlRot.GetY();
|
||||
currentRotZ = hlRot.GetZ();
|
||||
currentRotW = hlRot.GetW();
|
||||
#else
|
||||
// JS/WASM: re-activate sleeping bodies (Jolt deactivates even with mAllowSleeping=false in WASM)
|
||||
if (!physics.bodyInterface.IsActive(bodyId))
|
||||
physics.bodyInterface.ActivateBody(bodyId);
|
||||
|
||||
var p = physics.bodyInterface.GetPosition(bodyId);
|
||||
var q = physics.bodyInterface.GetRotation(bodyId);
|
||||
|
||||
#if js
|
||||
currentPosX = cast p.GetX();
|
||||
currentPosY = cast p.GetY();
|
||||
currentPosZ = cast p.GetZ();
|
||||
@ -513,17 +540,6 @@ class RigidBody extends Trait {
|
||||
currentRotY = cast q.GetY();
|
||||
currentRotZ = cast q.GetZ();
|
||||
currentRotW = cast q.GetW();
|
||||
// JS: getter return values use internal WASM wrappers - do NOT destroy
|
||||
#else
|
||||
currentPosX = p.GetX();
|
||||
currentPosY = p.GetY();
|
||||
currentPosZ = p.GetZ();
|
||||
currentRotX = q.GetX();
|
||||
currentRotY = q.GetY();
|
||||
currentRotZ = q.GetZ();
|
||||
currentRotW = q.GetW();
|
||||
p.delete();
|
||||
q.delete();
|
||||
#end
|
||||
}
|
||||
|
||||
@ -554,50 +570,78 @@ class RigidBody extends Trait {
|
||||
// Physics methods
|
||||
public function applyForce(force:Vec4, ?loc:Vec4) {
|
||||
activate();
|
||||
#if hl
|
||||
hlForce.Set(force.x, force.y, force.z);
|
||||
if (loc == null) {
|
||||
physics.bodyInterface.AddForce(bodyId, hlForce);
|
||||
} else {
|
||||
hlPosR.Set(loc.x, loc.y, loc.z);
|
||||
physics.bodyInterface.AddForceAtPosition(bodyId, hlForce, hlPosR);
|
||||
}
|
||||
#else
|
||||
if (loc == null) {
|
||||
var f = new jolt.Jt.Vec3(force.x, force.y, force.z);
|
||||
physics.bodyInterface.AddForce(bodyId, f);
|
||||
#if hl f.delete(); #end
|
||||
} else {
|
||||
var f = new jolt.Jt.Vec3(force.x, force.y, force.z);
|
||||
var l = new jolt.Jt.RVec3(loc.x, loc.y, loc.z);
|
||||
physics.bodyInterface.AddForceAtPosition(bodyId, f, l);
|
||||
#if hl f.delete(); l.delete(); #end
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
public function applyImpulse(impulse:Vec4, ?loc:Vec4) {
|
||||
activate();
|
||||
#if hl
|
||||
hlForce.Set(impulse.x, impulse.y, impulse.z);
|
||||
if (loc == null) {
|
||||
physics.bodyInterface.AddImpulse(bodyId, hlForce);
|
||||
} else {
|
||||
hlPosR.Set(loc.x, loc.y, loc.z);
|
||||
physics.bodyInterface.AddImpulseAtPosition(bodyId, hlForce, hlPosR);
|
||||
}
|
||||
#else
|
||||
if (loc == null) {
|
||||
var i = new jolt.Jt.Vec3(impulse.x, impulse.y, impulse.z);
|
||||
physics.bodyInterface.AddImpulse(bodyId, i);
|
||||
#if hl i.delete(); #end
|
||||
} else {
|
||||
var i = new jolt.Jt.Vec3(impulse.x, impulse.y, impulse.z);
|
||||
var l = new jolt.Jt.RVec3(loc.x, loc.y, loc.z);
|
||||
physics.bodyInterface.AddImpulseAtPosition(bodyId, i, l);
|
||||
#if hl i.delete(); l.delete(); #end
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
public function applyTorque(torque:Vec4) {
|
||||
activate();
|
||||
#if hl
|
||||
hlForce.Set(torque.x, torque.y, torque.z);
|
||||
physics.bodyInterface.AddTorque(bodyId, hlForce);
|
||||
#else
|
||||
var t = new jolt.Jt.Vec3(torque.x, torque.y, torque.z);
|
||||
physics.bodyInterface.AddTorque(bodyId, t);
|
||||
#if hl t.delete(); #end
|
||||
#end
|
||||
}
|
||||
|
||||
public function applyTorqueImpulse(impulse:Vec4) {
|
||||
activate();
|
||||
#if hl
|
||||
hlForce.Set(impulse.x, impulse.y, impulse.z);
|
||||
physics.bodyInterface.AddAngularImpulse(bodyId, hlForce);
|
||||
#else
|
||||
var i = new jolt.Jt.Vec3(impulse.x, impulse.y, impulse.z);
|
||||
physics.bodyInterface.AddAngularImpulse(bodyId, i);
|
||||
#if hl i.delete(); #end
|
||||
#end
|
||||
}
|
||||
|
||||
public function setLinearVelocity(v:Vec4) {
|
||||
#if hl
|
||||
hlVel.Set(v.x, v.y, v.z);
|
||||
physics.bodyInterface.SetLinearVelocity(bodyId, hlVel);
|
||||
#else
|
||||
var vel = new jolt.Jt.Vec3(v.x, v.y, v.z);
|
||||
physics.bodyInterface.SetLinearVelocity(bodyId, vel);
|
||||
#if hl vel.delete(); #end
|
||||
#end
|
||||
}
|
||||
|
||||
public function getLinearVelocity():Vec4 {
|
||||
@ -608,9 +652,13 @@ class RigidBody extends Trait {
|
||||
}
|
||||
|
||||
public function setAngularVelocity(v:Vec4) {
|
||||
#if hl
|
||||
hlVel.Set(v.x, v.y, v.z);
|
||||
physics.bodyInterface.SetAngularVelocity(bodyId, hlVel);
|
||||
#else
|
||||
var vel = new jolt.Jt.Vec3(v.x, v.y, v.z);
|
||||
physics.bodyInterface.SetAngularVelocity(bodyId, vel);
|
||||
#if hl vel.delete(); #end
|
||||
#end
|
||||
}
|
||||
|
||||
public function getAngularVelocity():Vec4 {
|
||||
@ -643,15 +691,23 @@ class RigidBody extends Trait {
|
||||
}
|
||||
|
||||
public function setPosition(pos:Vec4) {
|
||||
#if hl
|
||||
hlPos.Set(pos.x, pos.y, pos.z);
|
||||
physics.bodyInterface.SetPosition(bodyId, hlPos, 0);
|
||||
#else
|
||||
var p = new jolt.Jt.RVec3(pos.x, pos.y, pos.z);
|
||||
physics.bodyInterface.SetPosition(bodyId, p, 0);
|
||||
#if hl p.delete(); #end
|
||||
#end
|
||||
}
|
||||
|
||||
public function setRotation(rot:Quat) {
|
||||
#if hl
|
||||
hlQuat.Set(rot.x, rot.y, rot.z, rot.w);
|
||||
physics.bodyInterface.SetRotation(bodyId, hlQuat, 0);
|
||||
#else
|
||||
var q = new jolt.Jt.Quat(rot.x, rot.y, rot.z, rot.w);
|
||||
physics.bodyInterface.SetRotation(bodyId, q, 0);
|
||||
#if hl q.delete(); #end
|
||||
#end
|
||||
}
|
||||
|
||||
public function syncTransform() {
|
||||
|
||||
@ -67,10 +67,11 @@ def on_depsgraph_update_post(self):
|
||||
|
||||
# Send last operator to Krom
|
||||
wrd = bpy.data.worlds['Lnx']
|
||||
if state.proc_play is not None and state.target == 'krom' and wrd.lnx_live_patch:
|
||||
ops = bpy.context.window_manager.operators
|
||||
if len(ops) > 0 and ops[-1] is not None:
|
||||
live_patch.on_operator(ops[-1].bl_idname)
|
||||
if (state.proc_play is not None or make._viewport_processes) and state.target == 'krom' and wrd.lnx_live_patch:
|
||||
if not live_patch.on_depsgraph_update(depsgraph.updates):
|
||||
ops = bpy.context.window_manager.operators
|
||||
if len(ops) > 0 and ops[-1] is not None:
|
||||
live_patch.on_operator(ops[-1].bl_idname)
|
||||
|
||||
# Hacky solution to update leenkx props after operator executions.
|
||||
# bpy.context.active_operator doesn't always exist, in some cases
|
||||
|
||||
@ -32,6 +32,9 @@ else:
|
||||
__running = False
|
||||
"""Whether live patch is currently active"""
|
||||
|
||||
scene_cache = {}
|
||||
"""Keys: (event_id, object_name) -> cached value tuple"""
|
||||
|
||||
# Any object can act as a message bus owner
|
||||
msgbus_owner = object()
|
||||
|
||||
@ -65,6 +68,62 @@ def stop():
|
||||
bpy.msgbus.clear_by_owner(msgbus_owner)
|
||||
|
||||
|
||||
def get_obj_transforms(obj):
|
||||
loc = (round(obj.location.x, 6), round(obj.location.y, 6), round(obj.location.z, 6))
|
||||
rot = obj.rotation_euler.to_quaternion()
|
||||
rot = (round(rot.x, 6), round(rot.y, 6), round(rot.z, 6), round(rot.w, 6))
|
||||
scale = (round(obj.scale.x, 6), round(obj.scale.y, 6), round(obj.scale.z, 6))
|
||||
return loc, rot, scale
|
||||
|
||||
|
||||
def get_light_props(obj):
|
||||
light = obj.data
|
||||
color = (round(light.color[0], 6), round(light.color[1], 6), round(light.color[2], 6))
|
||||
energy = round(light.energy, 6)
|
||||
return color, energy
|
||||
|
||||
DEPSGRAPH_HANDLERS = {
|
||||
'is_updated_transform': [
|
||||
('obj_location', lambda obj: get_obj_transforms(obj)[0]),
|
||||
('obj_rotation', lambda obj: get_obj_transforms(obj)[1]),
|
||||
('obj_scale', lambda obj: get_obj_transforms(obj)[2]),
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def on_depsgraph_update(updates):
|
||||
if not __running:
|
||||
return False
|
||||
|
||||
changed = False
|
||||
|
||||
for update in updates:
|
||||
uid = update.id
|
||||
|
||||
if isinstance(uid, bpy.types.Object):
|
||||
name = uid.name
|
||||
|
||||
if update.is_updated_transform:
|
||||
for event_id, extractor in DEPSGRAPH_HANDLERS['is_updated_transform']:
|
||||
current = extractor(uid)
|
||||
cache_key = (event_id, name)
|
||||
if current != scene_cache.get(cache_key):
|
||||
scene_cache[cache_key] = current
|
||||
send_event(event_id)
|
||||
changed = True
|
||||
|
||||
if update.is_updated_shading and isinstance(uid.data, bpy.types.Light):
|
||||
color, energy = get_light_props(uid)
|
||||
for event_id, current in (('light_color', color), ('light_energy', energy)):
|
||||
cache_key = (event_id, uid.data.name)
|
||||
if current != scene_cache.get(cache_key):
|
||||
scene_cache[cache_key] = current
|
||||
send_event(event_id)
|
||||
changed = True
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
def patch_export():
|
||||
"""Re-export the current scene and update the game accordingly."""
|
||||
if not __running or state.proc_build is not None:
|
||||
|
||||
@ -33,8 +33,10 @@ def init_categories():
|
||||
lnx_nodes.add_category('Input', icon='GREASEPENCIL', section="basic")
|
||||
lnx_nodes.add_category('Native', icon='MEMORY', section="basic",
|
||||
description="The Native category contains nodes which interact with the system (Input/Output functionality, etc.) or Haxe.")
|
||||
|
||||
lnx_nodes.add_category('Browser', icon='URL', section="basic")
|
||||
lnx_nodes.add_category('Krom Runtime', icon='WINDOW', section="basic",
|
||||
description="Krom specific nodes for WebView, Networking, Window, Display, File and System operations etc.")
|
||||
|
||||
lnx_nodes.add_category('Camera', icon='OUTLINER_OB_CAMERA', section="data")
|
||||
lnx_nodes.add_category('Material', icon='MATERIAL', section="data")
|
||||
lnx_nodes.add_category('Light', icon='LIGHT', section="data")
|
||||
|
||||
16
leenkx/blender/lnx/logicnode/krom/LN_copy_to_clipboard.py
Normal file
16
leenkx/blender/lnx/logicnode/krom/LN_copy_to_clipboard.py
Normal file
@ -0,0 +1,16 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromCopyToClipboardNode(LnxLogicTreeNode):
|
||||
"""Copies the given text to the system clipboard"""
|
||||
bl_idname = 'LNKromCopyToClipboardNode'
|
||||
bl_label = 'Copy To Clipboard'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'system'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxStringSocket', 'Text')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
15
leenkx/blender/lnx/logicnode/krom/LN_delay_idle_sleep.py
Normal file
15
leenkx/blender/lnx/logicnode/krom/LN_delay_idle_sleep.py
Normal file
@ -0,0 +1,15 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromDelayIdleSleepNode(LnxLogicTreeNode):
|
||||
"""Delays idle sleep on mobile platforms to keep the runtime active"""
|
||||
bl_idname = 'LNKromDelayIdleSleepNode'
|
||||
bl_label = 'Delay Idle Sleep'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'system'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
16
leenkx/blender/lnx/logicnode/krom/LN_delete_file.py
Normal file
16
leenkx/blender/lnx/logicnode/krom/LN_delete_file.py
Normal file
@ -0,0 +1,16 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromDeleteFileNode(LnxLogicTreeNode):
|
||||
"""Deletes the file at the given path."""
|
||||
bl_idname = 'LNKromDeleteFileNode'
|
||||
bl_label = 'Delete File'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'file'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxStringSocket', 'Path')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
15
leenkx/blender/lnx/logicnode/krom/LN_file_exists.py
Normal file
15
leenkx/blender/lnx/logicnode/krom/LN_file_exists.py
Normal file
@ -0,0 +1,15 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromFileExistsNode(LnxLogicTreeNode):
|
||||
"""Checks whether a file exists at the given path"""
|
||||
bl_idname = 'LNKromFileExistsNode'
|
||||
bl_label = 'File Exists'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'file'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxStringSocket', 'Path')
|
||||
|
||||
self.add_output('LnxBoolSocket', 'Exists')
|
||||
15
leenkx/blender/lnx/logicnode/krom/LN_get_arg.py
Normal file
15
leenkx/blender/lnx/logicnode/krom/LN_get_arg.py
Normal file
@ -0,0 +1,15 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromGetArgNode(LnxLogicTreeNode):
|
||||
"""Returns the command-line argument at the given index"""
|
||||
bl_idname = 'LNKromGetArgNode'
|
||||
bl_label = 'Get Arg'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'system'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxIntSocket', 'Index')
|
||||
|
||||
self.add_output('LnxStringSocket', 'Arg')
|
||||
13
leenkx/blender/lnx/logicnode/krom/LN_get_arg_count.py
Normal file
13
leenkx/blender/lnx/logicnode/krom/LN_get_arg_count.py
Normal file
@ -0,0 +1,13 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromGetArgCountNode(LnxLogicTreeNode):
|
||||
"""Returns the number of command line arguments passed to the application"""
|
||||
bl_idname = 'LNKromGetArgCountNode'
|
||||
bl_label = 'Get Arg Count'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'system'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_output('LnxIntSocket', 'Count')
|
||||
13
leenkx/blender/lnx/logicnode/krom/LN_get_files_location.py
Normal file
13
leenkx/blender/lnx/logicnode/krom/LN_get_files_location.py
Normal file
@ -0,0 +1,13 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromGetFilesLocationNode(LnxLogicTreeNode):
|
||||
"""Returns the files location path for the application"""
|
||||
bl_idname = 'LNKromGetFilesLocationNode'
|
||||
bl_label = 'Get Files Location'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'system'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_output('LnxStringSocket', 'Path')
|
||||
13
leenkx/blender/lnx/logicnode/krom/LN_save_path.py
Normal file
13
leenkx/blender/lnx/logicnode/krom/LN_save_path.py
Normal file
@ -0,0 +1,13 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromSavePathNode(LnxLogicTreeNode):
|
||||
"""Returns the save path for the application."""
|
||||
bl_idname = 'LNKromSavePathNode'
|
||||
bl_label = 'Save Path'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'system'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_output('LnxStringSocket', 'Path')
|
||||
16
leenkx/blender/lnx/logicnode/krom/LN_set_application_name.py
Normal file
16
leenkx/blender/lnx/logicnode/krom/LN_set_application_name.py
Normal file
@ -0,0 +1,16 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromSetApplicationNameNode(LnxLogicTreeNode):
|
||||
"""Sets the application name used for save paths"""
|
||||
bl_idname = 'LNKromSetApplicationNameNode'
|
||||
bl_label = 'Set Application Name'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'system'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxStringSocket', 'Name')
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
16
leenkx/blender/lnx/logicnode/krom/LN_show_keyboard.py
Normal file
16
leenkx/blender/lnx/logicnode/krom/LN_show_keyboard.py
Normal file
@ -0,0 +1,16 @@
|
||||
from lnx.logicnode.lnx_nodes import *
|
||||
|
||||
|
||||
class KromShowKeyboardNode(LnxLogicTreeNode):
|
||||
"""Shows or hides the onscreen keyboard for mobile platforms"""
|
||||
bl_idname = 'LNKromShowKeyboardNode'
|
||||
bl_label = 'Show Keyboard'
|
||||
lnx_category = 'Krom Runtime'
|
||||
lnx_section = 'system'
|
||||
lnx_version = 1
|
||||
|
||||
def lnx_init(self, context):
|
||||
self.add_input('LnxNodeSocketAction', 'In')
|
||||
self.add_input('LnxBoolSocket', 'Show', default_value=True)
|
||||
|
||||
self.add_output('LnxNodeSocketAction', 'Out')
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user