Compare commits

..

60 Commits

Author SHA1 Message Date
fe017dd874 Full BSDF 2026-08-07 02:04:01 -07:00
7aeebf2008 Extend BRDF 2026-07-27 12:10:11 -07:00
0b4184ccc2 Merge branch 'main' of https://dev.leenkx.com/Onek8/LNXSDK 2026-07-24 17:02:15 -07:00
ddc12e8607 BSDF Shaders 2026-07-24 17:02:00 -07:00
6ad647ae56 Merge pull request 'main' (#132) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#132
2026-07-24 09:22:31 +00:00
b77aca926a Refactor shader sockets 2026-07-24 01:59:51 -07:00
c2bb20f905 Moises Jpelaez: 5.2 Updates 2026-07-23 23:41:13 -07:00
14c6a7be03 Merge pull request 'main' (#131) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#131
2026-07-24 06:13:01 +00:00
85d63e8413 Merge branch 'main' of https://dev.leenkx.com/Onek8/LNXSDK 2026-07-23 23:08:56 -07:00
78452aaf67 Finished Viewport 2026-07-23 23:02:14 -07:00
1f72636350 Merge pull request 'main' (#130) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#130
2026-07-23 07:00:06 +00:00
62433ce86a merge upstream 2026-07-23 06:58:51 +00:00
2be36398f7 Merge branch 'main' of https://dev.leenkx.com/Onek8/LNXSDK 2026-07-22 21:04:07 -07:00
2675138ddc Windows RunT/Krom WebView2 DX11 and OpenGL 2026-07-22 21:03:43 -07:00
572665e8e6 Merge pull request 'main' (#129) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#129
2026-07-22 04:01:11 +00:00
0839f39dfa merge upstream 2026-07-22 03:59:30 +00:00
57cf4955a1 Live patch - Light properties, object visibility and world 2026-07-21 20:57:36 -07:00
c52ae2e4f1 Merge pull request 'main' (#128) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#128
2026-07-21 03:26:52 +00:00
48141f23c5 Merge pull request 'MacOS arm64 Kmake' (#10) from Dante/LNXSDK:main into main
Reviewed-on: #10
2026-07-21 03:25:03 +00:00
cbbcd053fb MacOS arm64 Kmake 2026-07-20 20:15:25 -07:00
a57923860e Merge pull request 'main' (#127) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#127
2026-07-19 04:35:30 +00:00
160f6bdadf Viewport build 2026-07-18 21:33:47 -07:00
50ad462318 Live patch refactor 2026-07-18 19:49:25 -07:00
1239145da4 LivePatch Global 2026-07-18 16:32:51 -07:00
102941b5d2 Update 2026-07-18 16:31:21 -07:00
defff993a0 Merge pull request 'main' (#126) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#126
2026-07-18 16:24:34 +00:00
e408151295 merge upstream 2026-07-18 16:22:37 +00:00
22159c9f37 Delete leenkx/Sources/leenkx/logicnode/PlayActionFromNode.hx.backup 2026-07-18 16:22:17 +00:00
9a2779982d Update leenkx/Sources/iron/data/Geometry.hx 2026-07-18 16:21:39 +00:00
2fc7e9880a Upload files to "Krom" 2026-07-18 04:30:47 +00:00
7e1ac5fa5c Merge pull request 'main' (#125) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#125
2026-07-18 03:27:17 +00:00
b2395f30fc VOX_PATCH_2 + VOX_5 2026-07-16 23:49:44 -07:00
f4b0bf1e93 Merge pull request 'Webview for RunT/Krom' (#9) from Dante/LNXSDK:main into main
Reviewed-on: #9
2026-07-14 00:02:33 +00:00
31a6a9d7ec Webview for RunT/Krom 2026-07-13 15:44:52 -07:00
7b2f21c499 Missing particle node 2026-07-10 19:04:13 -07:00
17c31b4a4b FSR Probe fix 2026-07-10 15:56:10 -07:00
013c8653ff SSGI rewrite 2026-07-10 12:43:24 -07:00
bd8b49a416 Multithreaded windows 2026-07-09 23:59:31 -07:00
9d83c318b6 Jolt Patch 2026-07-09 17:25:48 -07:00
cb19c9b5b4 Update lib/aura/Backends/hl/aura/math/FFT.h 2026-07-09 04:26:08 +00:00
f4fe822ef6 Update leenkx/Sources/leenkx/renderpath/Sky.hx 2026-07-09 02:06:06 +00:00
6689fbc734 Merge pull request 'Incremental recompute' (#8) from Dante/LNXSDK:main into main
Reviewed-on: #8
2026-06-26 04:40:09 +00:00
91b6c203e9 Incremental recompute 2026-06-25 21:33:51 -07:00
2c30554504 Moises Jpelaez - CPU particle visual fixes 2026-06-24 20:33:46 -07:00
37c8779d12 Patch_5 2026-06-24 20:23:12 -07:00
6b704ff469 Merge pull request 'main' (#7) from Dante/LNXSDK:main into main
Reviewed-on: #7
2026-06-24 07:15:29 +00:00
2a3bff5a18 Nishita to Sky 2026-06-24 00:12:30 -07:00
91482071b8 merge upstream 2026-06-24 07:06:56 +00:00
38151eb233 Update 2026-06-24 00:05:37 -07:00
78ea055aea Update Aura 2026-06-23 14:54:15 -07:00
db2482dbe2 Update leenkx/Sources/leenkx/logicnode/LeenkxSendMessageNode.hx 2026-06-23 05:58:41 +00:00
5ae6a9e698 Merge pull request 'main' (#6) from Dante/LNXSDK:main into main
Reviewed-on: #6
2026-06-23 02:39:31 +00:00
6db83e559b merge upstream 2026-06-23 02:07:46 +00:00
e7ec872747 FSR buffer 2026-06-22 19:07:01 -07:00
31226a3871 Merge pull request 'Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx' (#5) from Dante/LNXSDK:main into main
Reviewed-on: #5
2026-06-22 23:57:45 +00:00
9be3240d6c Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx 2026-06-22 22:42:52 +00:00
96134404a2 Compute 0 2026-06-15 20:07:42 -07:00
3aac63d255 Update Kha/Backends/Kore-HL/kha/korehl/graphics4/Graphics.hx 2026-06-10 05:55:02 +00:00
a8d6095204 Update Kha/Backends/Kore-HL/kha/korehl/graphics4/Graphics.hx 2026-06-10 02:37:45 +00:00
960095d0d5 Upload files to "Krom" 2026-06-09 23:02:56 +00:00
236 changed files with 11141 additions and 3869 deletions

View File

@ -142,6 +142,8 @@ class Image implements Canvas implements Resource {
return 5;
case A16:
return 7;
case R32UI:
return 8;
default:
return 1; // Grey8
}

View File

@ -1,397 +1,397 @@
package kha.korehl.graphics4;
import kha.arrays.Float32Array;
import kha.graphics4.ComputeShader;
import kha.graphics4.CubeMap;
import kha.graphics4.MipMapFilter;
import kha.graphics4.PipelineState;
import kha.graphics4.ShaderStorageBuffer;
import kha.graphics4.TextureAddressing;
import kha.graphics4.TextureFilter;
import kha.graphics4.Usage;
import kha.graphics4.VertexBuffer;
import kha.math.FastMatrix3;
import kha.math.FastMatrix4;
import kha.math.FastVector2;
import kha.math.FastVector3;
import kha.math.FastVector4;
import kha.Canvas;
import kha.Image;
import kha.Video;
import kha.Color;
class Graphics implements kha.graphics4.Graphics {
var target: Canvas;
public function new(target: Canvas = null) {
this.target = target;
}
public function vsynced(): Bool {
return kinc_graphics_vsynced();
}
public function refreshRate(): Int {
return kinc_graphics_refreshrate();
}
public function clear(?color: Color, ?z: FastFloat, ?stencil: Int): Void {
var flags: Int = 0;
if (color != null)
flags |= 1;
if (z != null)
flags |= 2;
if (stencil != null)
flags |= 4;
kinc_graphics_clear(flags, color == null ? 0 : color.value, z, stencil);
}
public function viewport(x: Int, y: Int, width: Int, height: Int): Void {
kinc_graphics_viewport(x, y, width, height);
}
public function setVertexBuffer(vertexBuffer: kha.graphics4.VertexBuffer): Void {
kinc_graphics_set_vertexbuffer(vertexBuffer._buffer);
}
public function setVertexBuffers(vertexBuffers: Array<kha.graphics4.VertexBuffer>): Void {
kinc_graphics_set_vertexbuffers(vertexBuffers.length > 0 ? vertexBuffers[0]._buffer : null,
vertexBuffers.length > 1 ? vertexBuffers[1]._buffer : null, vertexBuffers.length > 2 ? vertexBuffers[2]._buffer : null,
vertexBuffers.length > 3 ? vertexBuffers[3]._buffer : null, vertexBuffers.length);
}
public function setIndexBuffer(indexBuffer: kha.graphics4.IndexBuffer): Void {
kinc_graphics_set_indexbuffer(indexBuffer._buffer);
}
public function maxTextureSize(): Int {
return 4096;
}
public function supportsNonPow2Textures(): Bool {
return false;
}
public function setCubeMap(unit: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void {
if (cubeMap == null)
return;
if (cubeMap._texture != null)
kinc_graphics_set_cubemap_texture(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, cubeMap._texture);
else
kinc_graphics_set_cubemap_target(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, cubeMap._renderTarget);
}
public function setCubeMapDepth(unit: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void {
if (cubeMap == null)
return;
kinc_graphics_set_cubemap_depth(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, cubeMap._renderTarget);
}
public function scissor(x: Int, y: Int, width: Int, height: Int): Void {
kinc_graphics_scissor(x, y, width, height);
}
public function disableScissor(): Void {
kinc_graphics_disable_scissor();
}
public function instancedRenderingAvailable(): Bool {
return true;
}
public function setTextureParameters(unit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing,
minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {
kinc_graphics_set_texture_parameters(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, uAddressing, vAddressing, minificationFilter,
magnificationFilter, mipmapFilter);
}
public function setTexture3DParameters(unit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing,
wAddressing: TextureAddressing, minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {
kinc_graphics_set_texture3d_parameters(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, uAddressing, vAddressing, wAddressing, minificationFilter,
magnificationFilter, mipmapFilter);
}
public function setTextureCompareMode(unit: kha.graphics4.TextureUnit, enabled: Bool) {
kinc_graphics_set_texture_compare_mode(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, enabled);
}
public function setCubeMapCompareMode(unit: kha.graphics4.TextureUnit, enabled: Bool) {
kinc_graphics_set_cube_map_compare_mode(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, enabled);
}
public function setTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
if (texture._texture != null)
kinc_graphics_set_texture(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._texture);
else
kinc_graphics_set_render_target(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._renderTarget);
}
public function setTextureArray(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
kinc_graphics_set_texture_array(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._textureArray);
}
public function setTextureDepth(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
kinc_graphics_set_texture_depth(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._renderTarget);
}
public function setVideoTexture(unit: kha.graphics4.TextureUnit, texture: kha.Video): Void {
if (texture == null)
return;
kinc_graphics_set_texture(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, Image.fromVideo(texture)._texture);
}
public function setImageTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
kinc_graphics_set_image_texture(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._texture);
}
public function maxBoundTextures(): Int {
return 8;
}
public function setPipeline(pipe: PipelineState): Void {
pipe.set();
}
public function setStencilReferenceValue(value: Int): Void {}
public function setBool(location: kha.graphics4.ConstantLocation, value: Bool): Void {
kinc_graphics_set_bool(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value);
}
public function setInt(location: kha.graphics4.ConstantLocation, value: Int): Void {
kinc_graphics_set_int(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value);
}
public function setInt2(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int): Void {
kinc_graphics_set_int2(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2);
}
public function setInt3(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int): Void {
kinc_graphics_set_int3(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2, value3);
}
public function setInt4(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int, value4: Int): Void {
kinc_graphics_set_int4(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2, value3, value4);
}
public function setInts(location: kha.graphics4.ConstantLocation, values: kha.arrays.Int32Array): Void {
kinc_graphics_set_ints(cast(location, kha.korehl.graphics4.ConstantLocation)._location, values.getData(), values.length);
}
public function setFloat(location: kha.graphics4.ConstantLocation, value: FastFloat): Void {
kinc_graphics_set_float(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value);
}
public function setFloat2(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat): Void {
kinc_graphics_set_float2(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2);
}
public function setFloat3(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat): Void {
kinc_graphics_set_float3(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2, value3);
}
public function setFloat4(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat, value4: FastFloat): Void {
kinc_graphics_set_float4(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2, value3, value4);
}
public function setVector2(location: kha.graphics4.ConstantLocation, value: FastVector2): Void {
kinc_graphics_set_float2(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value.x, value.y);
}
public function setVector3(location: kha.graphics4.ConstantLocation, value: FastVector3): Void {
kinc_graphics_set_float3(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value.x, value.y, value.z);
}
public function setVector4(location: kha.graphics4.ConstantLocation, value: FastVector4): Void {
kinc_graphics_set_float4(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value.x, value.y, value.z, value.w);
}
public function setFloats(location: kha.graphics4.ConstantLocation, values: Float32Array): Void {
kinc_graphics_set_floats(cast(location, kha.korehl.graphics4.ConstantLocation)._location, values.getData(), values.length);
}
public inline function setMatrix(location: kha.graphics4.ConstantLocation, matrix: FastMatrix4): Void {
kinc_graphics_set_matrix(cast(location, kha.korehl.graphics4.ConstantLocation)._location, matrix._00, matrix._10, matrix._20, matrix._30, matrix._01,
matrix._11, matrix._21, matrix._31, matrix._02, matrix._12, matrix._22, matrix._32, matrix._03, matrix._13, matrix._23, matrix._33);
}
public inline function setMatrix3(location: kha.graphics4.ConstantLocation, matrix: FastMatrix3): Void {
kinc_graphics_set_matrix3(cast(location, kha.korehl.graphics4.ConstantLocation)._location, matrix._00, matrix._10, matrix._20, matrix._01, matrix._11,
matrix._21, matrix._02, matrix._12, matrix._22);
}
public function drawIndexedVertices(start: Int = 0, count: Int = -1): Void {
if (count < 0)
kinc_graphics_draw_all_indexed_vertices();
else
kinc_graphics_draw_indexed_vertices(start, count);
}
public function drawIndexedVerticesInstanced(instanceCount: Int, start: Int = 0, count: Int = -1): Void {
if (count < 0)
kinc_graphics_draw_all_indexed_vertices_instanced(instanceCount);
else
kinc_graphics_draw_indexed_vertices_instanced(instanceCount, start, count);
}
function renderToTexture(additionalRenderTargets: Array<Canvas>): Void {
if (additionalRenderTargets != null) {
var len = additionalRenderTargets.length;
var rt0 = cast(target, Image)._renderTarget;
var rt1 = len > 0 ? cast(additionalRenderTargets[0], Image)._renderTarget : null;
var rt2 = len > 1 ? cast(additionalRenderTargets[1], Image)._renderTarget : null;
var rt3 = len > 2 ? cast(additionalRenderTargets[2], Image)._renderTarget : null;
var rt4 = len > 3 ? cast(additionalRenderTargets[3], Image)._renderTarget : null;
var rt5 = len > 4 ? cast(additionalRenderTargets[4], Image)._renderTarget : null;
var rt6 = len > 5 ? cast(additionalRenderTargets[5], Image)._renderTarget : null;
var rt7 = len > 6 ? cast(additionalRenderTargets[6], Image)._renderTarget : null;
kinc_graphics_render_to_textures(rt0, rt1, rt2, rt3, rt4, rt5, rt6, rt7, len + 1);
}
else {
kinc_graphics_render_to_texture(cast(target, Image)._renderTarget);
}
}
public function begin(additionalRenderTargets: Array<Canvas> = null): Void {
if (target == null)
kinc_graphics_restore_render_target();
else
renderToTexture(additionalRenderTargets);
}
public function beginFace(face: Int): Void {
kinc_graphics_render_to_face(cast(target, CubeMap)._renderTarget, face);
}
public function beginEye(eye: Int): Void {}
public function end(): Void {}
public function flush(): Void {
kinc_graphics_flush();
}
public function setShaderStorageBuffer(buffer: ShaderStorageBuffer, index: Int) {
// Kore::Compute::setBuffer(buffer->buffer, index);
}
public function setComputeShader(shader: ComputeShader) {
kinc_g4_set_compute_shader(shader._shader);
}
public function compute(x: Int, y: Int, z: Int) {
kinc_g4_compute(x, y, z);
}
@:hlNative("std", "kinc_graphics_clear") static function kinc_graphics_clear(flags: Int, color: Int, z: FastFloat, stencil: Int): Void {}
@:hlNative("std", "kinc_graphics_vsynced") static function kinc_graphics_vsynced(): Bool {
return false;
}
@:hlNative("std", "kinc_graphics_refreshrate") static function kinc_graphics_refreshrate(): Int {
return 0;
}
@:hlNative("std", "kinc_graphics_viewport") static function kinc_graphics_viewport(x: Int, y: Int, width: Int, height: Int): Void {}
@:hlNative("std", "kinc_graphics_set_vertexbuffer") static function kinc_graphics_set_vertexbuffer(buffer: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_vertexbuffers") static function kinc_graphics_set_vertexbuffers(b0: Pointer, b1: Pointer, b2: Pointer, b3: Pointer,
count: Int): Void {}
@:hlNative("std", "kinc_graphics_set_indexbuffer") static function kinc_graphics_set_indexbuffer(buffer: Pointer): Void {}
@:hlNative("std", "kinc_graphics_scissor") static function kinc_graphics_scissor(x: Int, y: Int, width: Int, height: Int): Void {}
@:hlNative("std", "kinc_graphics_disable_scissor") static function kinc_graphics_disable_scissor(): Void {}
@:hlNative("std", "kinc_graphics_set_texture_parameters") static function kinc_graphics_set_texture_parameters(unit: Pointer, uAddressing: Int,
vAddressing: Int, minificationFilter: Int, magnificationFilter: Int, mipmapFilter: Int): Void {}
@:hlNative("std", "kinc_graphics_set_texture3d_parameters") static function kinc_graphics_set_texture3d_parameters(unit: Pointer, uAddressing: Int,
vAddressing: Int, wAddressing: Int, minificationFilter: Int, magnificationFilter: Int, mipmapFilter: Int): Void {}
@:hlNative("std", "kinc_graphics_set_texture_compare_mode") static function kinc_graphics_set_texture_compare_mode(unit: Pointer, enabled: Bool): Void {}
@:hlNative("std", "kinc_graphics_set_cube_map_compare_mode") static function kinc_graphics_set_cube_map_compare_mode(unit: Pointer, enabled: Bool): Void {}
@:hlNative("std", "kinc_graphics_set_texture") static function kinc_graphics_set_texture(unit: Pointer, texture: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_texture_depth") static function kinc_graphics_set_texture_depth(unit: Pointer, renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_texture_array") static function kinc_graphics_set_texture_array(unit: Pointer, textureArray: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_render_target") static function kinc_graphics_set_render_target(unit: Pointer, renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_cubemap_texture") static function kinc_graphics_set_cubemap_texture(unit: Pointer, texture: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_cubemap_target") static function kinc_graphics_set_cubemap_target(unit: Pointer, renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_cubemap_depth") static function kinc_graphics_set_cubemap_depth(unit: Pointer, renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_image_texture") static function kinc_graphics_set_image_texture(unit: Pointer, texture: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_bool") static function kinc_graphics_set_bool(location: Pointer, value: Bool): Void {}
@:hlNative("std", "kinc_graphics_set_int") static function kinc_graphics_set_int(location: Pointer, value: Int): Void {}
@:hlNative("std", "kinc_graphics_set_int2") static function kinc_graphics_set_int2(location: Pointer, value1: Int, value2: Int): Void {}
@:hlNative("std", "kinc_graphics_set_int3") static function kinc_graphics_set_int3(location: Pointer, value1: Int, value2: Int, value3: Int): Void {}
@:hlNative("std", "kinc_graphics_set_int4") static function kinc_graphics_set_int4(location: Pointer, value1: Int, value2: Int, value3: Int,
value4: Int): Void {}
@:hlNative("std", "kinc_graphics_set_ints") static function kinc_graphics_set_ints(location: Pointer, values: Pointer, count: Int): Void {}
@:hlNative("std", "kinc_graphics_set_float") static function kinc_graphics_set_float(location: Pointer, value: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_float2") static function kinc_graphics_set_float2(location: Pointer, value1: FastFloat, value2: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_float3") static function kinc_graphics_set_float3(location: Pointer, value1: FastFloat, value2: FastFloat,
value3: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_float4") static function kinc_graphics_set_float4(location: Pointer, value1: FastFloat, value2: FastFloat,
value3: FastFloat, value4: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_floats") static function kinc_graphics_set_floats(location: Pointer, values: Pointer, count: Int): Void {}
@:hlNative("std", "kinc_graphics_set_matrix") static function kinc_graphics_set_matrix(location: Pointer, _00: FastFloat, _10: FastFloat, _20: FastFloat,
_30: FastFloat, _01: FastFloat, _11: FastFloat, _21: FastFloat, _31: FastFloat, _02: FastFloat, _12: FastFloat, _22: FastFloat, _32: FastFloat,
_03: FastFloat, _13: FastFloat, _23: FastFloat, _33: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_matrix3") static function kinc_graphics_set_matrix3(location: Pointer, _00: FastFloat, _10: FastFloat,
_20: FastFloat, _01: FastFloat, _11: FastFloat, _21: FastFloat, _02: FastFloat, _12: FastFloat, _22: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_draw_all_indexed_vertices") static function kinc_graphics_draw_all_indexed_vertices(): Void {}
@:hlNative("std", "kinc_graphics_draw_indexed_vertices") static function kinc_graphics_draw_indexed_vertices(start: Int, count: Int): Void {}
@:hlNative("std",
"kinc_graphics_draw_all_indexed_vertices_instanced") static function kinc_graphics_draw_all_indexed_vertices_instanced(instanceCount: Int): Void {}
@:hlNative("std", "kinc_graphics_draw_indexed_vertices_instanced") static function kinc_graphics_draw_indexed_vertices_instanced(instanceCount: Int,
start: Int, count: Int): Void {}
@:hlNative("std", "kinc_graphics_restore_render_target") static function kinc_graphics_restore_render_target(): Void {}
@:hlNative("std", "kinc_graphics_render_to_texture") static function kinc_graphics_render_to_texture(renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_render_to_textures") static function kinc_graphics_render_to_textures(rt0: Pointer, rt1: Pointer, rt2: Pointer,
rt3: Pointer, rt4: Pointer, rt5: Pointer, rt6: Pointer, rt7: Pointer, count: Int): Void {}
@:hlNative("std", "kinc_graphics_render_to_face") static function kinc_graphics_render_to_face(renderTarget: Pointer, face: Int): Void {}
@:hlNative("std", "kinc_graphics_flush") static function kinc_graphics_flush(): Void {}
@:hlNative("std", "kinc_g4_set_compute_shader") static function kinc_g4_set_compute_shader(shader: Pointer): Void {}
@:hlNative("std", "kinc_g4_compute") static function kinc_g4_compute(x: Int, y: Int, z: Int): Void {}
}
package kha.korehl.graphics4;
import kha.arrays.Float32Array;
import kha.graphics4.ComputeShader;
import kha.graphics4.CubeMap;
import kha.graphics4.MipMapFilter;
import kha.graphics4.PipelineState;
import kha.graphics4.ShaderStorageBuffer;
import kha.graphics4.TextureAddressing;
import kha.graphics4.TextureFilter;
import kha.graphics4.Usage;
import kha.graphics4.VertexBuffer;
import kha.math.FastMatrix3;
import kha.math.FastMatrix4;
import kha.math.FastVector2;
import kha.math.FastVector3;
import kha.math.FastVector4;
import kha.Canvas;
import kha.Image;
import kha.Video;
import kha.Color;
class Graphics implements kha.graphics4.Graphics {
var target: Canvas;
public function new(target: Canvas = null) {
this.target = target;
}
public function vsynced(): Bool {
return kinc_graphics_vsynced();
}
public function refreshRate(): Int {
return kinc_graphics_refreshrate();
}
public function clear(?color: Color, ?z: FastFloat, ?stencil: Int): Void {
var flags: Int = 0;
if (color != null)
flags |= 1;
if (z != null)
flags |= 2;
if (stencil != null)
flags |= 4;
kinc_graphics_clear(flags, color == null ? 0 : color.value, z, stencil);
}
public function viewport(x: Int, y: Int, width: Int, height: Int): Void {
kinc_graphics_viewport(x, y, width, height);
}
public function setVertexBuffer(vertexBuffer: kha.graphics4.VertexBuffer): Void {
kinc_graphics_set_vertexbuffer(vertexBuffer._buffer);
}
public function setVertexBuffers(vertexBuffers: Array<kha.graphics4.VertexBuffer>): Void {
kinc_graphics_set_vertexbuffers(vertexBuffers.length > 0 ? vertexBuffers[0]._buffer : null,
vertexBuffers.length > 1 ? vertexBuffers[1]._buffer : null, vertexBuffers.length > 2 ? vertexBuffers[2]._buffer : null,
vertexBuffers.length > 3 ? vertexBuffers[3]._buffer : null, vertexBuffers.length);
}
public function setIndexBuffer(indexBuffer: kha.graphics4.IndexBuffer): Void {
kinc_graphics_set_indexbuffer(indexBuffer._buffer);
}
public function maxTextureSize(): Int {
return 4096;
}
public function supportsNonPow2Textures(): Bool {
return false;
}
public function setCubeMap(unit: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void {
if (cubeMap == null)
return;
if (cubeMap._texture != null)
kinc_graphics_set_cubemap_texture(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, cubeMap._texture);
else
kinc_graphics_set_cubemap_target(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, cubeMap._renderTarget);
}
public function setCubeMapDepth(unit: kha.graphics4.TextureUnit, cubeMap: kha.graphics4.CubeMap): Void {
if (cubeMap == null)
return;
kinc_graphics_set_cubemap_depth(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, cubeMap._renderTarget);
}
public function scissor(x: Int, y: Int, width: Int, height: Int): Void {
kinc_graphics_scissor(x, y, width, height);
}
public function disableScissor(): Void {
kinc_graphics_disable_scissor();
}
public function instancedRenderingAvailable(): Bool {
return true;
}
public function setTextureParameters(unit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing,
minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {
kinc_graphics_set_texture_parameters(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, uAddressing, vAddressing, minificationFilter,
magnificationFilter, mipmapFilter);
}
public function setTexture3DParameters(unit: kha.graphics4.TextureUnit, uAddressing: TextureAddressing, vAddressing: TextureAddressing,
wAddressing: TextureAddressing, minificationFilter: TextureFilter, magnificationFilter: TextureFilter, mipmapFilter: MipMapFilter): Void {
kinc_graphics_set_texture3d_parameters(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, uAddressing, vAddressing, wAddressing, minificationFilter,
magnificationFilter, mipmapFilter);
}
public function setTextureCompareMode(unit: kha.graphics4.TextureUnit, enabled: Bool) {
kinc_graphics_set_texture_compare_mode(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, enabled);
}
public function setCubeMapCompareMode(unit: kha.graphics4.TextureUnit, enabled: Bool) {
kinc_graphics_set_cube_map_compare_mode(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, enabled);
}
public function setTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
if (texture._texture != null)
kinc_graphics_set_texture(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._texture);
else
kinc_graphics_set_render_target(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._renderTarget);
}
public function setTextureArray(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
kinc_graphics_set_texture_array(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._textureArray);
}
public function setTextureDepth(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
if (texture == null)
return;
kinc_graphics_set_texture_depth(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._renderTarget);
}
public function setVideoTexture(unit: kha.graphics4.TextureUnit, texture: kha.Video): Void {
if (texture == null)
return;
kinc_graphics_set_texture(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, Image.fromVideo(texture)._texture);
}
public function setImageTexture(unit: kha.graphics4.TextureUnit, texture: kha.Image): Void {
kinc_graphics_set_image_texture(cast(unit, kha.korehl.graphics4.TextureUnit)._unit, texture._texture);
}
public function maxBoundTextures(): Int {
return 8;
}
public function setPipeline(pipe: PipelineState): Void {
pipe.set();
}
public function setStencilReferenceValue(value: Int): Void {}
public function setBool(location: kha.graphics4.ConstantLocation, value: Bool): Void {
kinc_graphics_set_bool(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value);
}
public function setInt(location: kha.graphics4.ConstantLocation, value: Int): Void {
kinc_graphics_set_int(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value);
}
public function setInt2(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int): Void {
kinc_graphics_set_int2(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2);
}
public function setInt3(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int): Void {
kinc_graphics_set_int3(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2, value3);
}
public function setInt4(location: kha.graphics4.ConstantLocation, value1: Int, value2: Int, value3: Int, value4: Int): Void {
kinc_graphics_set_int4(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2, value3, value4);
}
public function setInts(location: kha.graphics4.ConstantLocation, values: kha.arrays.Int32Array): Void {
kinc_graphics_set_ints(cast(location, kha.korehl.graphics4.ConstantLocation)._location, values.getData(), values.length);
}
public function setFloat(location: kha.graphics4.ConstantLocation, value: FastFloat): Void {
kinc_graphics_set_float(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value);
}
public function setFloat2(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat): Void {
kinc_graphics_set_float2(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2);
}
public function setFloat3(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat): Void {
kinc_graphics_set_float3(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2, value3);
}
public function setFloat4(location: kha.graphics4.ConstantLocation, value1: FastFloat, value2: FastFloat, value3: FastFloat, value4: FastFloat): Void {
kinc_graphics_set_float4(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value1, value2, value3, value4);
}
public function setVector2(location: kha.graphics4.ConstantLocation, value: FastVector2): Void {
kinc_graphics_set_float2(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value.x, value.y);
}
public function setVector3(location: kha.graphics4.ConstantLocation, value: FastVector3): Void {
kinc_graphics_set_float3(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value.x, value.y, value.z);
}
public function setVector4(location: kha.graphics4.ConstantLocation, value: FastVector4): Void {
kinc_graphics_set_float4(cast(location, kha.korehl.graphics4.ConstantLocation)._location, value.x, value.y, value.z, value.w);
}
public function setFloats(location: kha.graphics4.ConstantLocation, values: Float32Array): Void {
kinc_graphics_set_floats(cast(location, kha.korehl.graphics4.ConstantLocation)._location, values.getData(), values.length);
}
public inline function setMatrix(location: kha.graphics4.ConstantLocation, matrix: FastMatrix4): Void {
kinc_graphics_set_matrix(cast(location, kha.korehl.graphics4.ConstantLocation)._location, matrix._00, matrix._10, matrix._20, matrix._30, matrix._01,
matrix._11, matrix._21, matrix._31, matrix._02, matrix._12, matrix._22, matrix._32, matrix._03, matrix._13, matrix._23, matrix._33);
}
public inline function setMatrix3(location: kha.graphics4.ConstantLocation, matrix: FastMatrix3): Void {
kinc_graphics_set_matrix3(cast(location, kha.korehl.graphics4.ConstantLocation)._location, matrix._00, matrix._10, matrix._20, matrix._01, matrix._11,
matrix._21, matrix._02, matrix._12, matrix._22);
}
public function drawIndexedVertices(start: Int = 0, count: Int = -1): Void {
if (count < 0)
kinc_graphics_draw_all_indexed_vertices();
else
kinc_graphics_draw_indexed_vertices(start, count);
}
public function drawIndexedVerticesInstanced(instanceCount: Int, start: Int = 0, count: Int = -1): Void {
if (count < 0)
kinc_graphics_draw_all_indexed_vertices_instanced(instanceCount);
else
kinc_graphics_draw_indexed_vertices_instanced(instanceCount, start, count);
}
function renderToTexture(additionalRenderTargets: Array<Canvas>): Void {
if (additionalRenderTargets != null) {
var len = additionalRenderTargets.length;
var rt0 = cast(target, Image)._renderTarget;
var rt1 = len > 0 ? cast(additionalRenderTargets[0], Image)._renderTarget : null;
var rt2 = len > 1 ? cast(additionalRenderTargets[1], Image)._renderTarget : null;
var rt3 = len > 2 ? cast(additionalRenderTargets[2], Image)._renderTarget : null;
var rt4 = len > 3 ? cast(additionalRenderTargets[3], Image)._renderTarget : null;
var rt5 = len > 4 ? cast(additionalRenderTargets[4], Image)._renderTarget : null;
var rt6 = len > 5 ? cast(additionalRenderTargets[5], Image)._renderTarget : null;
var rt7 = len > 6 ? cast(additionalRenderTargets[6], Image)._renderTarget : null;
kinc_graphics_render_to_textures(rt0, rt1, rt2, rt3, rt4, rt5, rt6, rt7, len + 1);
}
else {
kinc_graphics_render_to_texture(cast(target, Image)._renderTarget);
}
}
public function begin(additionalRenderTargets: Array<Canvas> = null): Void {
if (target == null)
kinc_graphics_restore_render_target();
else
renderToTexture(additionalRenderTargets);
}
public function beginFace(face: Int): Void {
kinc_graphics_render_to_face((target is CubeMap) ? cast(target, CubeMap)._renderTarget : cast(target, Image)._renderTarget, face);
}
public function beginEye(eye: Int): Void {}
public function end(): Void {}
public function flush(): Void {
kinc_graphics_flush();
}
public function setShaderStorageBuffer(buffer: ShaderStorageBuffer, index: Int) {
// Kore::Compute::setBuffer(buffer->buffer, index);
}
public function setComputeShader(shader: ComputeShader) {
kinc_g4_set_compute_shader(shader._shader);
}
public function compute(x: Int, y: Int, z: Int) {
kinc_g4_compute(x, y, z);
}
@:hlNative("std", "kinc_graphics_clear") static function kinc_graphics_clear(flags: Int, color: Int, z: FastFloat, stencil: Int): Void {}
@:hlNative("std", "kinc_graphics_vsynced") static function kinc_graphics_vsynced(): Bool {
return false;
}
@:hlNative("std", "kinc_graphics_refreshrate") static function kinc_graphics_refreshrate(): Int {
return 0;
}
@:hlNative("std", "kinc_graphics_viewport") static function kinc_graphics_viewport(x: Int, y: Int, width: Int, height: Int): Void {}
@:hlNative("std", "kinc_graphics_set_vertexbuffer") static function kinc_graphics_set_vertexbuffer(buffer: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_vertexbuffers") static function kinc_graphics_set_vertexbuffers(b0: Pointer, b1: Pointer, b2: Pointer, b3: Pointer,
count: Int): Void {}
@:hlNative("std", "kinc_graphics_set_indexbuffer") static function kinc_graphics_set_indexbuffer(buffer: Pointer): Void {}
@:hlNative("std", "kinc_graphics_scissor") static function kinc_graphics_scissor(x: Int, y: Int, width: Int, height: Int): Void {}
@:hlNative("std", "kinc_graphics_disable_scissor") static function kinc_graphics_disable_scissor(): Void {}
@:hlNative("std", "kinc_graphics_set_texture_parameters") static function kinc_graphics_set_texture_parameters(unit: Pointer, uAddressing: Int,
vAddressing: Int, minificationFilter: Int, magnificationFilter: Int, mipmapFilter: Int): Void {}
@:hlNative("std", "kinc_graphics_set_texture3d_parameters") static function kinc_graphics_set_texture3d_parameters(unit: Pointer, uAddressing: Int,
vAddressing: Int, wAddressing: Int, minificationFilter: Int, magnificationFilter: Int, mipmapFilter: Int): Void {}
@:hlNative("std", "kinc_graphics_set_texture_compare_mode") static function kinc_graphics_set_texture_compare_mode(unit: Pointer, enabled: Bool): Void {}
@:hlNative("std", "kinc_graphics_set_cube_map_compare_mode") static function kinc_graphics_set_cube_map_compare_mode(unit: Pointer, enabled: Bool): Void {}
@:hlNative("std", "kinc_graphics_set_texture") static function kinc_graphics_set_texture(unit: Pointer, texture: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_texture_depth") static function kinc_graphics_set_texture_depth(unit: Pointer, renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_texture_array") static function kinc_graphics_set_texture_array(unit: Pointer, textureArray: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_render_target") static function kinc_graphics_set_render_target(unit: Pointer, renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_cubemap_texture") static function kinc_graphics_set_cubemap_texture(unit: Pointer, texture: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_cubemap_target") static function kinc_graphics_set_cubemap_target(unit: Pointer, renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_cubemap_depth") static function kinc_graphics_set_cubemap_depth(unit: Pointer, renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_image_texture") static function kinc_graphics_set_image_texture(unit: Pointer, texture: Pointer): Void {}
@:hlNative("std", "kinc_graphics_set_bool") static function kinc_graphics_set_bool(location: Pointer, value: Bool): Void {}
@:hlNative("std", "kinc_graphics_set_int") static function kinc_graphics_set_int(location: Pointer, value: Int): Void {}
@:hlNative("std", "kinc_graphics_set_int2") static function kinc_graphics_set_int2(location: Pointer, value1: Int, value2: Int): Void {}
@:hlNative("std", "kinc_graphics_set_int3") static function kinc_graphics_set_int3(location: Pointer, value1: Int, value2: Int, value3: Int): Void {}
@:hlNative("std", "kinc_graphics_set_int4") static function kinc_graphics_set_int4(location: Pointer, value1: Int, value2: Int, value3: Int,
value4: Int): Void {}
@:hlNative("std", "kinc_graphics_set_ints") static function kinc_graphics_set_ints(location: Pointer, values: Pointer, count: Int): Void {}
@:hlNative("std", "kinc_graphics_set_float") static function kinc_graphics_set_float(location: Pointer, value: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_float2") static function kinc_graphics_set_float2(location: Pointer, value1: FastFloat, value2: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_float3") static function kinc_graphics_set_float3(location: Pointer, value1: FastFloat, value2: FastFloat,
value3: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_float4") static function kinc_graphics_set_float4(location: Pointer, value1: FastFloat, value2: FastFloat,
value3: FastFloat, value4: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_floats") static function kinc_graphics_set_floats(location: Pointer, values: Pointer, count: Int): Void {}
@:hlNative("std", "kinc_graphics_set_matrix") static function kinc_graphics_set_matrix(location: Pointer, _00: FastFloat, _10: FastFloat, _20: FastFloat,
_30: FastFloat, _01: FastFloat, _11: FastFloat, _21: FastFloat, _31: FastFloat, _02: FastFloat, _12: FastFloat, _22: FastFloat, _32: FastFloat,
_03: FastFloat, _13: FastFloat, _23: FastFloat, _33: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_set_matrix3") static function kinc_graphics_set_matrix3(location: Pointer, _00: FastFloat, _10: FastFloat,
_20: FastFloat, _01: FastFloat, _11: FastFloat, _21: FastFloat, _02: FastFloat, _12: FastFloat, _22: FastFloat): Void {}
@:hlNative("std", "kinc_graphics_draw_all_indexed_vertices") static function kinc_graphics_draw_all_indexed_vertices(): Void {}
@:hlNative("std", "kinc_graphics_draw_indexed_vertices") static function kinc_graphics_draw_indexed_vertices(start: Int, count: Int): Void {}
@:hlNative("std",
"kinc_graphics_draw_all_indexed_vertices_instanced") static function kinc_graphics_draw_all_indexed_vertices_instanced(instanceCount: Int): Void {}
@:hlNative("std", "kinc_graphics_draw_indexed_vertices_instanced") static function kinc_graphics_draw_indexed_vertices_instanced(instanceCount: Int,
start: Int, count: Int): Void {}
@:hlNative("std", "kinc_graphics_restore_render_target") static function kinc_graphics_restore_render_target(): Void {}
@:hlNative("std", "kinc_graphics_render_to_texture") static function kinc_graphics_render_to_texture(renderTarget: Pointer): Void {}
@:hlNative("std", "kinc_graphics_render_to_textures") static function kinc_graphics_render_to_textures(rt0: Pointer, rt1: Pointer, rt2: Pointer,
rt3: Pointer, rt4: Pointer, rt5: Pointer, rt6: Pointer, rt7: Pointer, count: Int): Void {}
@:hlNative("std", "kinc_graphics_render_to_face") static function kinc_graphics_render_to_face(renderTarget: Pointer, face: Int): Void {}
@:hlNative("std", "kinc_graphics_flush") static function kinc_graphics_flush(): Void {}
@:hlNative("std", "kinc_g4_set_compute_shader") static function kinc_g4_set_compute_shader(shader: Pointer): Void {}
@:hlNative("std", "kinc_g4_compute") static function kinc_g4_compute(x: Int, y: Int, z: Int): Void {}
}

View File

@ -234,6 +234,8 @@ class Image implements Canvas implements Resource {
return 5;
case A16:
return 7;
case R32UI:
return 8;
default:
return 1; // Grey8
}

View File

@ -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,
@ -114,6 +115,7 @@ extern class Krom {
static function windowWidth(id: Int): Int;
static function windowHeight(id: Int): Int;
static function setWindowTitle(id: Int, title: String): Void;
static function windowSetForeground(id: Int): Void;
static function screenDpi(): Int;
static function systemId(): String;
static function requestShutdown(): Void;
@ -158,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;
}

View File

@ -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;
}
}

View File

@ -30,15 +30,15 @@ class LoaderImpl {
}
public static function loadSoundFromDescription(desc: Dynamic, done: kha.Sound->Void, failed: AssetError->Void) {
var sound = Krom.loadSound(desc.files[0]);
if (sound == null) {
var sound = new kha.krom.Sound(desc.files[0]);
if (sound.uncompressedData == null) {
failed({
url: desc.files.join(","),
error: "Could not load sound(s)",
});
}
else {
done(new kha.krom.Sound(Bytes.ofData(sound)));
done(sound);
}
}

View File

@ -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,

View File

@ -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 {}

View File

@ -1,22 +1,25 @@
package kha.graphics4;
import haxe.io.Bytes;
import kha.Blob;
class ComputeShader {
public function new(sources: Array<Blob>, files: Array<String>) {
}
public function delete(): Void {
}
public function getConstantLocation(name: String): ConstantLocation {
return null;
}
public function getTextureUnit(name: String): TextureUnit {
return null;
}
}
package kha.graphics4;
import haxe.io.Bytes;
import kha.Blob;
class ComputeShader {
public var shader_: Dynamic;
public function new(sources: Array<Blob>, files: Array<String>) {
shader_ = Krom.createShaderCompute(sources[0].toBytes().getData());
}
public function delete(): Void {
Krom.deleteShaderCompute(shader_);
shader_ = null;
}
public function getConstantLocation(name: String): ConstantLocation {
return Krom.getConstantLocationCompute(shader_, name);
}
public function getTextureUnit(name: String): TextureUnit {
return Krom.getTextureUnitCompute(shader_, name);
}
}

View File

@ -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,
@ -261,10 +266,10 @@ class Graphics implements kha.graphics4.Graphics {
}
public function setComputeShader(shader: ComputeShader) {
Krom.setShaderCompute(shader.shader_);
}
public function compute(x: Int, y: Int, z: Int) {
Krom.compute(x, y, z);
}
}

View File

@ -2,24 +2,28 @@ package kha.krom;
import haxe.io.Bytes;
using StringTools;
class Sound extends kha.Sound {
public function new(bytes: Bytes) {
public function new(filename: String) {
super();
var count = Std.int(bytes.length / 4);
uncompressedData = new kha.arrays.Float32Array(count);
for (i in 0...count) {
uncompressedData[i] = bytes.getFloat(i * 4);
}
var sound = Krom.loadSound(filename);
if (sound != null) {
var bytes = Bytes.ofData(sound.buffer);
var count = Std.int(bytes.length / 4);
uncompressedData = new kha.arrays.Float32Array(count);
for (i in 0...count) {
uncompressedData[i] = bytes.getFloat(i * 4);
}
compressedData = null;
this.sampleRate = sound.sampleRate;
this.channels = sound.channels;
this.length = sound.length;
}
}
override public function uncompress(done: Void->Void): Void {
done();
}
override public function unload(): Void {
super.unload();
}
}

View File

@ -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
}

View File

@ -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);

View File

@ -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) {

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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.

Before

Width:  |  Height:  |  Size: 417 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 417 KiB

After

Width:  |  Height:  |  Size: 281 KiB

View File

@ -68,7 +68,7 @@ class Sound implements Resource {
var soundBytes = output.getBytes();
var count = Std.int(soundBytes.length / 4);
if (header.channel == 1) {
length = count / kha.audio2.Audio.samplesPerSecond; // header.sampleRate;
length = count / header.sampleRate;
uncompressedData = new kha.arrays.Float32Array(count * 2);
for (i in 0...count) {
uncompressedData[i * 2 + 0] = soundBytes.getFloat(i * 4);
@ -76,7 +76,7 @@ class Sound implements Resource {
}
}
else {
length = count / 2 / kha.audio2.Audio.samplesPerSecond; // header.sampleRate;
length = count / 2 / header.sampleRate;
uncompressedData = new kha.arrays.Float32Array(count);
for (i in 0...count) {
uncompressedData[i] = soundBytes.getFloat(i * 4);

View File

@ -0,0 +1,7 @@
package kha.compute;
enum abstract Access(Int) to Int {
var Read = 0;
var Write = 1;
var ReadWrite = 2;
}

View 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;
}

View File

@ -0,0 +1,3 @@
package kha.compute;
interface ConstantLocation {}

View 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;
}

View 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;
}

View File

@ -0,0 +1,3 @@
package kha.compute;
interface TextureUnit {}

View File

@ -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.

Binary file not shown.

Binary file not shown.

View File

@ -7,7 +7,7 @@ bl_info = {
"description": "Full Stack SDK",
"author": "Leenkx.com",
"version": (2026, 5, 0),
"blender": (4, 5, 0),
"blender": (5, 2, 0),
"doc_url": "https://leenkx.com/",
"tracker_url": "https://leenkx.com/support"
}

View File

@ -6,6 +6,7 @@
uniform sampler2D tex;
uniform sampler2D gbuffer0; // Roughness
uniform sampler2D gbufferD; // Depth
uniform vec2 dirInv;
@ -14,19 +15,46 @@ out vec4 fragColor;
void main() {
float roughness = textureLod(gbuffer0, texCoord, 0.0).b;
// if (roughness == 0.0) { // Always blur for now, non blured output can produce noise
// fragColor.rgb = textureLod(tex, texCoord).rgb;
// return;
// }
if (roughness >= 0.8) { // No reflections
if (roughness >= 0.8) {
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
return;
}
fragColor.rgb = textureLod(tex, texCoord + dirInv * 2.5, 0.0).rgb;
fragColor.rgb += textureLod(tex, texCoord + dirInv * 1.5, 0.0).rgb;
fragColor.rgb += textureLod(tex, texCoord, 0.0).rgb;
fragColor.rgb += textureLod(tex, texCoord - dirInv * 1.5, 0.0).rgb;
fragColor.rgb += textureLod(tex, texCoord - dirInv * 2.5, 0.0).rgb;
fragColor.rgb /= vec3(5.0);
if (roughness < 0.01) {
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
return;
}
float blurRadius = 1.0 + roughness * 4.0;
vec3 center = textureLod(tex, texCoord, 0.0).rgb;
float centerDepth = textureLod(gbufferD, texCoord, 0.0).r;
float w0 = 1.0 / (1.0 + roughness * 2.0);
float w1 = 1.0 / (1.0 + roughness);
float w2 = 1.0 / (1.0 + roughness * 0.5);
float totalW = w0;
fragColor.rgb = center * w0;
vec2 offsets[4];
offsets[0] = dirInv * blurRadius * 2.5;
offsets[1] = dirInv * blurRadius * 1.5;
offsets[2] = -dirInv * blurRadius * 1.5;
offsets[3] = -dirInv * blurRadius * 2.5;
float weights[4];
weights[0] = w2;
weights[1] = w1;
weights[2] = w1;
weights[3] = w2;
for (int i = 0; i < 4; i++) {
vec2 sampleTC = texCoord + offsets[i];
float sampleDepth = textureLod(gbufferD, sampleTC, 0.0).r;
float depthWeight = exp(-abs(centerDepth - sampleDepth) * 100.0);
float w = weights[i] * depthWeight;
fragColor.rgb += textureLod(tex, sampleTC, 0.0).rgb * w;
totalW += w;
}
fragColor.rgb /= vec3(totalW);
}

View File

@ -17,10 +17,12 @@ in vec3 wnormal;
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
| GBUF_IDX_1 | || base color (RGB) | occlusion/specular |
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
| GBUF_IDX_2 | _gbuffer2 || velocity (XY) | ignore radiance | unused |
| GBUF_IDX_2 | _gbuffer2 || velocity (XY) | ignore radiance | tangent angle |
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
| GBUF_IDX_EMISSION | _EmissionShaded || emission color (RGB) | unused |
+-------------------+-----------------++--------------+--------------+-----------------+--------------------+
| GBUF_IDX_REFRACTION | _SSRefraction || packed IOR | transmittance | surfaceDepth | unused |
| | _VoxelRefract || (0-1 range) | | | |
The indices as well as the GBUF_SIZE define are defined in "compiled.inc".
*/
@ -52,6 +54,10 @@ void main() {
#endif
#ifdef _SSRefraction
fragColor[GBUF_IDX_REFRACTION] = vec4(ior, opacity, 0.0, 0.0);
fragColor[GBUF_IDX_REFRACTION] = vec4(packIOR(ior), opacity, 0.0, 1.0);
#endif
#ifdef _Anisotropy
fragColor[GBUF_IDX_2].a = -1.0;
#endif
}

View File

@ -7,7 +7,11 @@ out vec4 fragColor[GBUF_SIZE];
void main() {
fragColor[GBUF_IDX_0] = vec4(1.0, 1.0, 0.0, 1.0);
#if GBUF_SIZE > 1
fragColor[GBUF_IDX_1] = vec4(color, 1.0);
#else
fragColor[GBUF_IDX_0] = vec4(color, 1.0);
#endif
#ifdef _EmissionShaded
fragColor[GBUF_IDX_EMISSION] = vec4(0.0);

View File

@ -8,12 +8,10 @@
#ifdef _Irr
#include "std/shirr.glsl"
#endif
#ifdef _SSS
#include "std/sss.glsl"
#endif
#ifdef _SSRS
#include "std/ssrs.glsl"
#endif
#include "std/brdf.glsl"
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
@ -25,6 +23,9 @@ uniform sampler2D gbuffer1;
#ifdef _EmissionShaded
uniform sampler2D gbufferEmission;
#endif
#ifdef _ClearCoat
uniform sampler2D gbufferCoatNormal;
#endif
#ifdef _VoxelGI
uniform sampler2D voxels_diffuse;
@ -91,7 +92,7 @@ uniform mat4 invVP;
#ifdef _SinglePoint
//!uniform sampler2DShadow shadowMapSpot[1];
//!uniform sampler2D shadowMapSpotTransparent[1];
//!uniform mat4 LWVPSpot[1];
//!uniform mat4 LWVPSpotArray[1];
#endif
#ifdef _Clusters
//!uniform sampler2DShadow shadowMapSpot[4];
@ -136,7 +137,7 @@ uniform vec2 cameraPlane;
#ifdef _ShadowMapTransparent
//!uniform sampler2D shadowMapSpotTransparent[1];
#endif
//!uniform mat4 LWVPSpot[1];
//!uniform mat4 LWVPSpotArray[1];
#else
//!uniform samplerCubeShadow shadowMapPoint[1];
#ifdef _ShadowMapTransparent
@ -199,6 +200,7 @@ uniform vec3 sunCol;
uniform sampler2D shadowMapAtlasSunTransparent;
#endif
#endif
//!uniform vec4 tileBoundsSunArray[maxLights * shadowmapCascades];
#else
uniform sampler2DShadow shadowMap;
#ifdef _ShadowMapTransparent
@ -235,6 +237,9 @@ uniform float time;
#endif
#include "std/light.glsl"
#ifdef _SSS
#include "std/sss.glsl"
#endif
in vec2 texCoord;
in vec3 viewRay;
@ -254,13 +259,41 @@ void main() {
float metallic;
uint matid;
unpackFloatInt16(g0.a, metallic, matid);
#ifdef _ExtBRDF
matid = min(matid, uint(MAX_MATERIALS - 1));
//!uniform vec4 materialParams[MAX_MATERIALS * 8];
vec4 matp0 = vec4(0.0), matp1 = vec4(0.0), matp2 = vec4(0.0), matp3 = vec4(0.0);
vec4 matp4 = vec4(0.0), matp5 = vec4(0.0), matp6 = vec4(0.0), matp7 = vec4(0.0);
// TODO: coatIOR=1.5, ior=1.45, thinWall=1.0 move to python make files
matp1.z = 1.5;
matp3.x = 1.45;
matp3.y = 1.0;
if (matid >= 3u) {
getMaterialParams(matid, matp0, matp1, matp2, matp3, matp4, matp5, matp6, matp7);
}
#ifdef _ClearCoat
vec3 coatTintCol = vec3(matp1.w, matp2.x, matp2.y);
#endif
#ifdef _Sheen
vec3 sheenTintCol = vec3(matp5.z, matp5.w, matp6.x);
#endif
#ifdef _SSS
vec3 sssColorVal = vec3(matp4.w, matp5.x, matp5.y);
vec3 sssRadiusBase = vec3(matp4.x, matp4.y, matp4.z);
float sssRadiusScalar = max(max(matp4.x, matp4.y), matp4.z) * matp7.x;
#endif
#endif
vec2 occspec = unpackFloat2(g1.a);
// re-investigate clamp basecolor to prevent extreme values causing glitches
vec3 basecolor = min(g1.rgb, vec3(2.0));
vec3 albedo = surfaceAlbedo(basecolor, metallic);
vec3 f0 = surfaceF0(basecolor, metallic);
#ifdef _ExtBRDF
f0 = mix(f0, basecolor, vec3(matp6.y, matp6.z, matp6.w));
#endif
#ifdef _VRStereo
bool isLeftEye = texCoord.x < 0.5;
vec3 eyePos = isLeftEye ? eyeLeft : eyeRight;
@ -279,10 +312,26 @@ void main() {
#endif
float dotNV = max(dot(n, v), 0.0);
#ifdef _ClearCoat
vec4 gCoat = textureLod(gbufferCoatNormal, texCoord, 0.0);
vec3 nCoat;
nCoat.z = 1.0 - abs(gCoat.x) - abs(gCoat.y);
nCoat.xy = nCoat.z >= 0.0 ? gCoat.xy : octahedronWrap(gCoat.xy);
nCoat = normalize(nCoat);
#endif
#ifdef _gbuffer2
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
#endif
#ifdef _Anisotropy
#ifdef _gbuffer2
vec3 wTangent = decodeTangent(g2.a, n);
#else
vec3 wTangent = vec3(0.0);
#endif
#endif
#ifdef _MicroShadowing
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
@ -295,6 +344,44 @@ void main() {
vec3 F = f0;
#endif
#ifdef _ExtBRDF
float iblSheenWeight = 1.0;
float iblCoatWeight = 1.0;
float iblLayerWeight = 1.0;
vec3 coatTintAbsorb = vec3(1.0);
#ifdef _Sheen
float sheenAlb = sheenIBLAlbedo(matp0.z, matp0.w, dotNV);
iblSheenWeight = max(1.0 - sheenAlb *
max(max(sheenTintCol.r, sheenTintCol.g), sheenTintCol.b), 0.0);
#endif
#ifdef _ClearCoat
float dotNVCoat = max(dot(nCoat, v), 0.0);
float coatF = coatIBLFresnel(matp1.x, matp1.z, dotNVCoat);
iblCoatWeight = max(1.0 - coatF, 0.0);
coatTintAbsorb = mix(vec3(1.0), clamp(coatTintCol, 0.0, 1.0),
clamp(1.0 / max(dotNVCoat, 0.3) * 0.2, 0.0, 1.0));
#endif
iblLayerWeight = iblSheenWeight * iblCoatWeight;
brdf_sheenWeight = iblSheenWeight;
brdf_coatWeight = iblCoatWeight;
brdf_coatTintAbsorb = coatTintAbsorb;
#ifdef _Sheen
brdf_sheenAlbedo = sheenAlb;
#endif
#ifdef _ClearCoat
brdf_coatF0 = (matp1.z - 1.0) / (matp1.z + 1.0);
brdf_coatF0 = brdf_coatF0 * brdf_coatF0;
#endif
#ifdef _Transmission
brdf_transmissionF0 = (matp3.x - 1.0) / (matp3.x + 1.0);
brdf_transmissionF0 = brdf_transmissionF0 * brdf_transmissionF0;
#endif
#endif // _ExtBRDF
#ifndef _VoxelAOvar
#ifndef _VoxelGI
// Envmap
@ -302,9 +389,7 @@ void main() {
vec3 envl = shIrradiance(n, shirr);
#ifdef _gbuffer2
if (g2.b < 0.5) {
envl = envl;
} else {
if (g2.b >= 0.5) {
envl = vec3(0.0);
}
#endif
@ -317,16 +402,21 @@ void main() {
#endif
#ifdef _Rad
#ifdef _Anisotropy
vec3 reflectionWorld = anisotropicIBLDirection(n, v, wTangent,
matp0.x, roughness);
#else
vec3 reflectionWorld = reflect(-v, n);
#endif
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
prefilteredColor = min(prefilteredColor, vec3(20.0));
#endif
#ifdef _EnvLDR
envl.rgb = pow(envl.rgb, vec3(2.2));
envl.rgb = srgbToLinear(envl.rgb);
#ifdef _Rad
prefilteredColor = pow(prefilteredColor, vec3(2.2));
prefilteredColor = srgbToLinear(prefilteredColor);
#endif
#endif
@ -344,6 +434,68 @@ void main() {
#endif
#endif
#ifdef _ExtBRDF
envl.rgb *= iblLayerWeight;
#ifdef _Transmission
float transF = transmissionIBLFresnel(matp3.x, dotNV);
float transmittance = 1.0 - transF;
#ifdef _Rad
if (matp2.z > 0.0 && transmittance > 0.0) {
vec3 refrDir;
if (matp3.y > 0.5) {
refrDir = reflect(-v, n);
} else {
refrDir = transmissionIBLDirection(n, v, matp3.x);
}
float transLod = getMipFromRoughness(matp2.w, envmapNumMipmaps);
vec3 transColor = textureLod(senvmapRadiance,
envMapEquirect(refrDir), transLod).rgb;
transColor = min(transColor, vec3(20.0));
#ifdef _EnvLDR
transColor = srgbToLinear(transColor);
#endif
envl.rgb += albedo * matp2.z * transmittance * transColor * dotNV
* iblLayerWeight;
}
#endif
#endif
#ifdef _ClearCoat
envl.rgb *= coatTintAbsorb;
#ifdef _Rad
if (coatF > 0.0) {
float coatLod = getMipFromRoughness(matp1.y, envmapNumMipmaps);
vec3 coatRefl = reflect(-v, nCoat);
vec3 coatColor = textureLod(senvmapRadiance,
envMapEquirect(coatRefl), coatLod).rgb;
coatColor = min(coatColor, vec3(20.0));
#ifdef _EnvLDR
coatColor = srgbToLinear(coatColor);
#endif
envl.rgb += coatColor * coatF * iblSheenWeight;
}
#endif
#endif
#ifdef _Sheen
#ifdef _Rad
if (sheenAlb > 0.0) {
float sheenLod = getMipFromRoughness(matp0.w, envmapNumMipmaps);
vec3 sheenRefl = reflect(-v, n);
vec3 sheenColor = textureLod(senvmapRadiance,
envMapEquirect(sheenRefl), sheenLod).rgb;
sheenColor = min(sheenColor, vec3(20.0));
#ifdef _EnvLDR
sheenColor = srgbToLinear(sheenColor);
#endif
envl.rgb += sheenColor * sheenTintCol * sheenAlb;
}
#endif
#endif
#endif // _ExtBRDF
envl.rgb *= envmapStrength * occspec.x;
fragColor.rgb = envl;
@ -352,11 +504,30 @@ void main() {
#ifdef _VoxelGI
fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff;
if(roughness < 1.0 && occspec.y > 0.0)
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl;
if(roughness < 1.0) {
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl * occspec.y;
}
#ifdef _Rad
vec3 iblReflection = reflect(-v, n);
float iblLod = getMipFromRoughness(roughness, envmapNumMipmaps);
vec3 iblPrefiltered = textureLod(senvmapRadiance, envMapEquirect(iblReflection), iblLod).rgb;
iblPrefiltered = min(iblPrefiltered, vec3(20.0));
#ifdef _EnvLDR
iblPrefiltered = srgbToLinear(iblPrefiltered);
#endif
#ifdef _ExtBRDF
iblPrefiltered *= iblLayerWeight;
iblPrefiltered *= coatTintAbsorb;
#endif
fragColor.rgb += iblPrefiltered * F * envmapStrength * occspec.x;
#else
#ifdef _EnvCol
fragColor.rgb += backgroundCol * F * envmapStrength * occspec.x;
#endif
#endif
#else
#ifdef _VoxelAOvar
fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc;
fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb;
#endif
#endif
@ -379,7 +550,7 @@ void main() {
#ifdef _SSGI
vec3 ssgiColor = textureLod(ssgitex, texCoord, 0.0).rgb;
fragColor.rgb += ssgiColor * albedo;
fragColor.rgb += ssgiColor * basecolor;
#endif
#ifdef _EmissionShadeless
@ -406,10 +577,42 @@ void main() {
float sdotVH = max(0.0, dot(v, sh));
float sdotNL = max(0.0, dot(n, sunDir));
vec3 svisibility = vec3(1.0);
#ifdef _Anisotropy
vec3 sdirect;
if (abs(matp0.x) > 0.001 && dot(wTangent, wTangent) > 0.001) {
vec3 sbitangent = normalize(cross(n, wTangent));
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
anisotropicBRDF(f0, roughness, matp0.x, matp0.y,
wTangent, sbitangent, n, sunDir, v, sdotNL, dotNV) * occspec.y;
} else {
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
}
#else
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
#endif
#ifdef _ExtBRDF
float sunLayerWeight;
sdirect = applyExtBRDFLayers(sdirect, albedo, f0, roughness,
sdotNL, dotNV, sdotNH, sdotVH, n, sunDir, v, sh
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
#endif
#ifdef _Sheen
, matp0.z, matp0.w, sheenTintCol
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
, sunLayerWeight);
#endif
#ifdef _ShadowMap
#ifdef _ShadowMapAtlas
tileBounds = tileBoundsSunArray[0];
#endif
#ifdef _CSM
svisibility = shadowTestCascade(
#ifdef _ShadowMapAtlas
@ -494,23 +697,17 @@ void main() {
fragColor.rgb += sdirect * sunCol * svisibility;
// #ifdef _Hair // Aniso
// if (matid == 2) {
// const float shinyParallel = roughness;
// const float shinyPerpendicular = 0.1;
// const vec3 v = vec3(0.99146, 0.11664, 0.05832);
// vec3 T = abs(dot(n, v)) > 0.99999 ? cross(n, vec3(0.0, 1.0, 0.0)) : cross(n, v);
// fragColor.rgb = orenNayarDiffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH) + wardSpecular(n, h, dotNL, dotNV, dotNH, T, shinyParallel, shinyPerpendicular) * spec;
// }
// #endif
#ifdef _SSS
if (matid == 2) {
#ifdef _ExtBRDF
if (matid >= 3u && matp3.z > 0.0) {
#ifdef _CSM
int casi, casindex;
mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex);
#endif
fragColor.rgb += fragColor.rgb * SSSSTransmittance(
vec3 sssColor = sssColorVal;
float sssRadius = sssRadiusScalar;
float sssStrength = matp3.z;
vec3 sssResult = SSSSTransmittance(
LWVP, p, n, sunDir, lightPlane.y,
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
@ -521,12 +718,26 @@ void main() {
#else
shadowMap
#endif
);//TODO implement transparent shadowmaps into the SSSSTransmittance()
, sssColor, sssRadius
#ifdef _ShadowMapAtlas
#ifdef _CSM
, tileBoundsSunArray[casi]
#else
, tileBoundsSunArray[0]
#endif
#endif
);
fragColor.rgb += sunCol * sssStrength * sssResult;
}
#endif
#endif
#endif // _Sun
#ifdef _ShadowMapAtlas
tileBounds = vec4(0.0, 0.0, 1.0, 1.0);
#endif
#ifdef _SinglePoint
#ifdef _VRStereo
@ -555,12 +766,53 @@ void main() {
#ifdef _SSRS
, gbufferD, invVP, eye
#endif
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
#endif
#ifdef _Sheen
, matp0.z, matp0.w, sheenTintCol
#endif
#ifdef _Anisotropy
, matp0.x, matp0.y, wTangent
#endif
#ifdef _SSS
, matp3.z, sssColorVal, sssRadiusBase * matp7.x, matp3.w
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
);
#ifdef _Spot
#ifdef _SSS
#ifdef _ShadowMap
if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot[0], p, n, normalize(lightPos - p), lightPlane.y, shadowMapSpot[0]);//TODO implement transparent shadowmaps into the SSSSTransmittance()
#ifdef _ExtBRDF
if (matid >= 3u && matp3.z > 0.0) {
vec3 sssColorSpot = sssColorVal;
float sssRadiusSpot = sssRadiusScalar;
float sssStrengthSpot = matp3.z;
fragColor.rgb += pointCol * sssStrengthSpot * SSSSTransmittance(LWVPSpotArray[0], p, n, normalize(lightPos - p), lightPlane.y, shadowMapSpot[0], sssColorSpot, sssRadiusSpot
#ifdef _ShadowMapAtlas
, vec4(0.0, 0.0, 1.0, 1.0)
#endif
);//TODO implement transparent shadowmaps into the SSSSTransmittance()
}
#endif
#endif
#endif
#endif
#ifndef _Spot
#ifdef _SSS
#ifdef _ShadowMap
#ifdef _ExtBRDF
if (matid >= 3u && matp3.z > 0.0) {
vec3 sssColorPoint = sssColorVal;
float sssRadiusPoint = sssRadiusScalar;
float sssStrengthPoint = matp3.z;
fragColor.rgb += pointCol * sssStrengthPoint * SSSSTransmittanceCube(shadowMapPoint[0], lightPos, p, n, normalize(lightPos - p), lightPlane.y, lightProj, sssColorPoint, sssRadiusPoint);
}
#endif
#endif
#endif
#endif
@ -618,7 +870,96 @@ void main() {
#ifdef _SSRS
, gbufferD, invVP, eye
#endif
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
#endif
#ifdef _Sheen
, matp0.z, matp0.w, sheenTintCol
#endif
#ifdef _Anisotropy
, matp0.x, matp0.y, wTangent
#endif
#ifdef _SSS
, matp3.z, sssColorVal, sssRadiusBase * matp7.x, matp3.w
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
);
#ifdef _SSS
#ifdef _ShadowMap
#ifdef _ExtBRDF
if (matid >= 3u && matp3.z > 0.0) {
vec3 sssColorCL = sssColorVal;
float sssRadiusCL = sssRadiusScalar;
float sssStrengthCL = matp3.z;
vec3 cLightPos = lightsArray[li * 3].xyz;
vec3 cLightCol = lightsArray[li * 3 + 1].xyz;
vec3 cLightDir = normalize(cLightPos - p);
#ifdef _Spot
bool isSpotLight = lightsArray[li * 3 + 2].y != 0.0;
if (isSpotLight) {
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[li], p, n, cLightDir, lightPlane.y, shadowMapAtlasSpot, sssColorCL, sssRadiusCL, tileBoundsSpotArray[li]);
#else
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[li], p, n, cLightDir, lightPlane.y, shadowMapAtlas, sssColorCL, sssRadiusCL, tileBoundsSpotArray[li]);
#endif
#else
if (li == 0) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[0], p, n, cLightDir, lightPlane.y, shadowMapSpot[0], sssColorCL, sssRadiusCL
#ifdef _ShadowMapAtlas
, vec4(0.0, 0.0, 1.0, 1.0)
#endif
);
else if (li == 1) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[1], p, n, cLightDir, lightPlane.y, shadowMapSpot[1], sssColorCL, sssRadiusCL
#ifdef _ShadowMapAtlas
, vec4(0.0, 0.0, 1.0, 1.0)
#endif
);
else if (li == 2) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[2], p, n, cLightDir, lightPlane.y, shadowMapSpot[2], sssColorCL, sssRadiusCL
#ifdef _ShadowMapAtlas
, vec4(0.0, 0.0, 1.0, 1.0)
#endif
);
else if (li == 3) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittance(LWVPSpotArray[3], p, n, cLightDir, lightPlane.y, shadowMapSpot[3], sssColorCL, sssRadiusCL
#ifdef _ShadowMapAtlas
, vec4(0.0, 0.0, 1.0, 1.0)
#endif
);
#endif
} else {
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCubeAtlas(shadowMapAtlasPoint, cLightPos, p, n, cLightDir, lightPlane.y, lightProj, li, sssColorCL, sssRadiusCL);
#else
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCubeAtlas(shadowMapAtlas, cLightPos, p, n, cLightDir, lightPlane.y, lightProj, li, sssColorCL, sssRadiusCL);
#endif
#else
if (li == 0) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[0], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
else if (li == 1) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[1], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
else if (li == 2) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[2], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
else if (li == 3) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[3], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
#endif
}
#else
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCubeAtlas(shadowMapAtlasPoint, cLightPos, p, n, cLightDir, lightPlane.y, lightProj, li, sssColorCL, sssRadiusCL);
#else
fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCubeAtlas(shadowMapAtlas, cLightPos, p, n, cLightDir, lightPlane.y, lightProj, li, sssColorCL, sssRadiusCL);
#endif
#else
if (li == 0) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[0], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
else if (li == 1) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[1], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
else if (li == 2) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[2], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
else if (li == 3) fragColor.rgb += cLightCol * sssStrengthCL * SSSSTransmittanceCube(shadowMapPoint[3], cLightPos, p, n, cLightDir, lightPlane.y, lightProj, sssColorCL, sssRadiusCL);
#endif
#endif
}
#endif
#endif
#endif
}
#endif // _Clusters

View File

@ -138,6 +138,16 @@
"link": "_cascadeData",
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
},
{
"name": "tileBoundsSunArray",
"link": "_tileBoundsSunArray",
"ifdef": ["_Sun", "_ShadowMap", "_ShadowMapAtlas"]
},
{
"name": "tileBoundsSpotArray",
"link": "_tileBoundsSpotArray",
"ifdef": ["_Clusters", "_Spot", "_ShadowMap", "_ShadowMapAtlas"]
},
{
"name": "lightPlane",
"link": "_lightPlane",
@ -277,8 +287,15 @@
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "materialParams",
"link": "_materialParams",
"type": "floats",
"ifdef": ["_ExtBRDF"]
}
],
"texture_units": [],
"vertex_shader": "../include/pass_viewray.vert.glsl",
"fragment_shader": "deferred_light.frag.glsl",
"color_attachments": ["RGBA64"]

View File

@ -3,6 +3,7 @@
#include "compiled.inc"
#include "std/gbuffer.glsl"
#include "std/math.glsl"
#include "std/brdf.glsl"
#ifdef _Clusters
#include "std/clusters.glsl"
#endif
@ -13,6 +14,12 @@
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1;
#ifdef _gbuffer2
uniform sampler2D gbuffer2;
#endif
#ifdef _ClearCoat
uniform sampler2D gbufferCoatNormal;
#endif
uniform float envmapStrength;
#ifdef _Irr
@ -49,7 +56,7 @@ uniform vec2 cameraPlane;
#ifdef _SinglePoint
#ifdef _Spot
//!uniform sampler2DShadow shadowMapSpot[1];
//!uniform mat4 LWVPSpot[1];
//!uniform mat4 LWVPSpotArray[1];
#else
//!uniform samplerCubeShadow shadowMapPoint[1];
//!uniform vec2 lightProj;
@ -91,6 +98,7 @@ uniform vec3 sunCol;
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSun;
#endif
//!uniform vec4 tileBoundsSunArray[maxLights * shadowmapCascades];
#else
uniform sampler2DShadow shadowMap;
#endif
@ -132,17 +140,61 @@ void main() {
float metallic;
uint matid;
unpackFloatInt16(g0.a, metallic, matid);
#ifdef _ExtBRDF
matid = min(matid, uint(MAX_MATERIALS - 1));
//!uniform vec4 materialParams[MAX_MATERIALS * 8];
vec4 matp0 = vec4(0.0), matp1 = vec4(0.0), matp2 = vec4(0.0), matp3 = vec4(0.0);
vec4 matp4 = vec4(0.0), matp5 = vec4(0.0), matp6 = vec4(0.0), matp7 = vec4(0.0);
// TODO: coatIOR=1.5, ior=1.45, thinWall=1.0 move to python make files
matp1.z = 1.5;
matp3.x = 1.45;
matp3.y = 1.0;
if (matid >= 3u) {
getMaterialParams(matid, matp0, matp1, matp2, matp3, matp4, matp5, matp6, matp7);
}
#ifdef _ClearCoat
vec3 coatTintCol = vec3(matp1.w, matp2.x, matp2.y);
#endif
#ifdef _Sheen
vec3 sheenTintCol = vec3(matp5.z, matp5.w, matp6.x);
#endif
#ifdef _SSS
vec3 sssColorVal = vec3(matp4.w, matp5.x, matp5.y);
vec3 sssRadiusScaled = vec3(matp4.x, matp4.y, matp4.z) * matp7.x;
#endif
#endif
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
vec2 occspec = unpackFloat2(g1.a);
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
vec3 f0 = surfaceF0(g1.rgb, metallic);
#ifdef _ExtBRDF
f0 = mix(f0, min(g1.rgb, vec3(2.0)), vec3(matp6.y, matp6.z, matp6.w));
#endif
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
vec3 v = normalize(eye - p);
float dotNV = max(dot(n, v), 0.0);
#ifdef _ClearCoat
vec4 gCoat = textureLod(gbufferCoatNormal, texCoord, 0.0);
vec3 nCoat;
nCoat.z = 1.0 - abs(gCoat.x) - abs(gCoat.y);
nCoat.xy = nCoat.z >= 0.0 ? gCoat.xy : octahedronWrap(gCoat.xy);
nCoat = normalize(nCoat);
#endif
#ifdef _Anisotropy
#ifdef _gbuffer2
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
vec3 wTangent = decodeTangent(g2.a, n);
#else
vec3 wTangent = vec3(0.0);
#endif
#endif
#ifdef _Brdf
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
#endif
@ -158,15 +210,20 @@ void main() {
#endif
#ifdef _Rad
#ifdef _Anisotropy
vec3 reflectionWorld = anisotropicIBLDirection(n, v, wTangent,
matp0.x, roughness);
#else
vec3 reflectionWorld = reflect(-v, n);
#endif
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
#endif
#ifdef _EnvLDR
envl.rgb = pow(envl.rgb, vec3(2.2));
envl.rgb = srgbToLinear(envl.rgb);
#ifdef _Rad
prefilteredColor = pow(prefilteredColor, vec3(2.2));
prefilteredColor = srgbToLinear(prefilteredColor);
#endif
#endif
@ -180,6 +237,98 @@ void main() {
#endif
#endif
#ifdef _ExtBRDF
float iblSheenWeight = 1.0;
float iblCoatWeight = 1.0;
vec3 coatTintAbsorb = vec3(1.0);
#ifdef _Sheen
float sheenAlb = sheenIBLAlbedo(matp0.z, matp0.w, dotNV);
iblSheenWeight = max(1.0 - sheenAlb *
max(max(sheenTintCol.r, sheenTintCol.g), sheenTintCol.b), 0.0);
#endif
#ifdef _ClearCoat
float dotNVCoat = max(dot(nCoat, v), 0.0);
float coatF = coatIBLFresnel(matp1.x, matp1.z, dotNVCoat);
iblCoatWeight = max(1.0 - coatF, 0.0);
if (matp1.x > 0.0) {
coatTintAbsorb = mix(vec3(1.0), clamp(coatTintCol, 0.0, 1.0),
clamp(1.0 / max(dotNVCoat, 0.3) * 0.2, 0.0, 1.0));
}
#endif
float iblLayerWeight = iblSheenWeight * iblCoatWeight;
envl.rgb *= iblLayerWeight;
brdf_sheenWeight = iblSheenWeight;
brdf_coatWeight = iblCoatWeight;
brdf_coatTintAbsorb = coatTintAbsorb;
#ifdef _Sheen
brdf_sheenAlbedo = sheenAlb;
#endif
#ifdef _ClearCoat
brdf_coatF0 = (matp1.z - 1.0) / (matp1.z + 1.0);
brdf_coatF0 = brdf_coatF0 * brdf_coatF0;
#endif
#ifdef _Transmission
brdf_transmissionF0 = (matp3.x - 1.0) / (matp3.x + 1.0);
brdf_transmissionF0 = brdf_transmissionF0 * brdf_transmissionF0;
#endif
#ifdef _Transmission
float transF = transmissionIBLFresnel(matp3.x, dotNV);
float transmittance = 1.0 - transF;
#ifdef _Rad
if (matp2.z > 0.0 && transmittance > 0.0) {
vec3 refrDir = transmissionIBLDirection(n, v, matp3.x);
float transLod = getMipFromRoughness(matp2.w, envmapNumMipmaps);
vec3 transColor = textureLod(senvmapRadiance,
envMapEquirect(refrDir), transLod).rgb;
transColor = min(transColor, vec3(20.0));
#ifdef _EnvLDR
transColor = srgbToLinear(transColor);
#endif
envl.rgb += albedo * matp2.z * transmittance * transColor * dotNV
* iblLayerWeight;
}
#endif
#endif
#ifdef _ClearCoat
envl.rgb *= coatTintAbsorb;
#ifdef _Rad
if (coatF > 0.0) {
float coatLod = getMipFromRoughness(matp1.y, envmapNumMipmaps);
vec3 coatRefl = reflect(-v, nCoat);
vec3 coatColor = textureLod(senvmapRadiance,
envMapEquirect(coatRefl), coatLod).rgb;
coatColor = min(coatColor, vec3(20.0));
#ifdef _EnvLDR
coatColor = srgbToLinear(coatColor);
#endif
envl.rgb += coatColor * coatF * iblSheenWeight;
}
#endif
#endif
#ifdef _Sheen
#ifdef _Rad
if (sheenAlb > 0.0) {
float sheenLod = getMipFromRoughness(matp0.w, envmapNumMipmaps);
vec3 sheenRefl = reflect(-v, n);
vec3 sheenColor = textureLod(senvmapRadiance,
envMapEquirect(sheenRefl), sheenLod).rgb;
sheenColor = min(sheenColor, vec3(20.0));
#ifdef _EnvLDR
sheenColor = srgbToLinear(sheenColor);
#endif
envl.rgb += sheenColor * sheenTintCol * sheenAlb;
}
#endif
#endif
#endif // _ExtBRDF
envl.rgb *= envmapStrength * occspec.x;
fragColor.rgb = envl;
@ -189,10 +338,50 @@ void main() {
float sdotVH = max(0.0, dot(v, sh));
float sdotNL = max(0.0, dot(n, sunDir));
float svisibility = 1.0;
#ifdef _Anisotropy
vec3 sdirect;
if (abs(matp0.x) > 0.001 && dot(wTangent, wTangent) > 0.001) {
vec3 sbitangent = normalize(cross(n, wTangent));
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
anisotropicBRDF(f0, roughness, matp0.x, matp0.y,
wTangent, sbitangent, n, sunDir, v, sdotNL, dotNV) * occspec.y;
} else {
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
}
#else
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
#endif
float sunSheenWeight = brdf_sheenWeight;
float sunCoatWeight = brdf_coatWeight;
#ifdef _Sheen
vec3 sunSheen = sheenBRDF(matp0.z, matp0.w, sheenTintCol, sdotNL, sdotNH, dotNV);
#endif
#ifdef _ClearCoat
vec3 sunCoat = clearcoatBRDF(matp1.x, matp1.y, matp1.z, nCoat, sunDir, v, sh);
#endif
float sunLayerWeight = sunSheenWeight * sunCoatWeight;
sdirect *= sunLayerWeight;
#ifdef _Transmission
sdirect += transmissionBRDF(albedo, matp2.z, matp2.w, matp3.x, matp3.y, sdotNL, dotNV, sdotVH) * sunLayerWeight;
#endif
#ifdef _ClearCoat
sdirect *= brdf_coatTintAbsorb;
sdirect += sunCoat * sunSheenWeight;
#endif
#ifdef _Sheen
sdirect += sunSheen;
#endif
#ifdef _ShadowMap
#ifdef _ShadowMapAtlas
tileBounds = tileBoundsSunArray[0];
#endif
#ifdef _CSM
svisibility = shadowTestCascade(
#ifdef _ShadowMapAtlas
@ -235,6 +424,21 @@ void main() {
#ifdef _Spot
, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight // TODO: Test!
#endif
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
#endif
#ifdef _Sheen
, matp0.z, matp0.w, sheenTintCol
#endif
#ifdef _Anisotropy
, matp0.x, matp0.y, wTangent
#endif
#ifdef _SSS
, matp3.z, sssColorVal, sssRadiusScaled, matp3.w
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
);
#endif
@ -277,7 +481,29 @@ void main() {
, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale
, lightsArraySpot[li * 2 + 1].xyz // right
#endif
#ifdef _ClearCoat
, matp1.x, matp1.y, matp1.z, coatTintCol, nCoat
#endif
#ifdef _Sheen
, matp0.z, matp0.w, sheenTintCol
#endif
#ifdef _Anisotropy
, matp0.x, matp0.y, wTangent
#endif
#ifdef _SSS
, matp3.z, sssColorVal, sssRadiusScaled, matp3.w
#endif
#ifdef _Transmission
, matp2.z, matp2.w, matp3.x, matp3.y
#endif
);
}
#endif // _Clusters
fragColor.rgb = clamp(fragColor.rgb, vec3(0.0), vec3(65504.0));
if (any(isnan(fragColor.rgb)) || any(isinf(fragColor.rgb))) {
fragColor.rgb = vec3(0.0);
}
fragColor.a = 1.0; // Mark as opaque
}

View File

@ -97,6 +97,16 @@
"link": "_cascadeData",
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
},
{
"name": "tileBoundsSunArray",
"link": "_tileBoundsSunArray",
"ifdef": ["_Sun", "_ShadowMap", "_ShadowMapAtlas"]
},
{
"name": "tileBoundsSpotArray",
"link": "_tileBoundsSpotArray",
"ifdef": ["_Clusters", "_Spot", "_ShadowMap", "_ShadowMapAtlas"]
},
{
"name": "eyeLookRight",
"link": "_eyeLookRight",
@ -214,6 +224,12 @@
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "materialParams",
"link": "_materialParams",
"type": "floats",
"ifdef": ["_ExtBRDF"]
}
],
"vertex_shader": "../include/pass_viewray.vert.glsl",

View File

@ -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);

View File

@ -11,6 +11,7 @@ uniform sampler2D gbuffer1; // basecol, spec
uniform mat4 P;
uniform mat3 V3;
uniform vec2 cameraProj;
uniform vec2 screenSize;
#ifdef _CPostprocess
uniform vec3 PPComp9;
@ -24,8 +25,8 @@ out vec4 fragColor;
vec3 hitCoord;
float depth;
const int numBinarySearchSteps = 7;
const int maxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);
const int numBinarySearchSteps = 8;
const int maxSteps = 50;
vec2 getProjectedCoord(const vec3 hit) {
vec4 projectedCoord = P * vec4(hit, 1.0);
@ -38,44 +39,58 @@ vec2 getProjectedCoord(const vec3 hit) {
}
float getDeltaDepth(const vec3 hit) {
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
vec2 tc = getProjectedCoord(hit);
if (tc.x < 0.0 || tc.x > 1.0 || tc.y < 0.0 || tc.y > 1.0)
return -1.0;
depth = textureLod(gbufferD, tc, 0.0).r * 2.0 - 1.0;
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
return viewPos.z - hit.z;
}
vec4 binarySearch(vec3 dir) {
vec4 binarySearch(vec3 dir, float stepSize) {
float ddepth;
for (int i = 0; i < numBinarySearchSteps; i++) {
dir *= 0.5;
hitCoord -= dir;
stepSize *= 0.5;
hitCoord -= dir * stepSize;
ddepth = getDeltaDepth(hitCoord);
if (ddepth < 0.0) hitCoord += dir;
if (ddepth < 0.0) hitCoord += dir * stepSize;
}
// Ugly discard of hits too far away
#ifdef _CPostprocess
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
float maxDist = PPComp9.z;
#else
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
float maxDist = ssrSearchDist;
#endif
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
if (abs(ddepth) > maxDist * 0.005) return vec4(0.0);
vec2 hitTC = getProjectedCoord(hitCoord);
if (hitTC.x < 0.0 || hitTC.x > 1.0 || hitTC.y < 0.0 || hitTC.y > 1.0)
return vec4(0.0);
return vec4(hitTC, 0.0, 1.0);
}
vec4 rayCast(vec3 dir) {
#ifdef _CPostprocess
dir *= PPComp9.x;
float baseStep = PPComp9.x;
float maxDist = PPComp9.z;
#else
dir *= ssrRayStep;
float baseStep = ssrRayStep;
float maxDist = ssrSearchDist;
#endif
float stepSize = baseStep * max(1.0, -viewRay.z * 0.1);
vec3 startPos = hitCoord;
for (int i = 0; i < maxSteps; i++) {
hitCoord += dir;
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
hitCoord += dir * stepSize;
float dist = length(hitCoord - startPos);
if (dist > maxDist) break;
float ddepth = getDeltaDepth(hitCoord);
if (ddepth > 0.0) return binarySearch(dir, stepSize);
stepSize *= 1.03;
}
return vec4(0.0);
}
void main() {
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
float roughness = unpackFloat(g0.b).y;
float roughness = g0.b;
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
@ -92,30 +107,54 @@ void main() {
vec3 viewNormal = V3 * n;
vec3 viewPos = getPosView(viewRay, d, cameraProj);
vec3 reflected = reflect(viewPos, viewNormal);
float NdotV = clamp(dot(viewNormal, -normalize(viewPos)), 0.0, 1.0);
vec3 reflected = reflect(normalize(viewPos), viewNormal);
hitCoord = viewPos;
#ifdef _CPostprocess
vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0;
#else
vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0;
#endif
vec3 dir = reflected;
// * max(ssrMinRayStep, -viewPos.z)
vec4 coords = rayCast(dir);
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
if (coords.w <= 0.0) {
fragColor.rgb = vec3(0.0);
return;
}
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
float screenEdgeFactor = smoothstep(0.5, 0.15, deltaCoords.x)
* smoothstep(0.5, 0.15, deltaCoords.y);
screenEdgeFactor = max(screenEdgeFactor, 0.15);
float hitDepth = textureLod(gbufferD, coords.xy, 0.0).r * 2.0 - 1.0;
vec3 hitViewPos = getPosView(viewRay, hitDepth, cameraProj);
vec3 hitDir = normalize(hitViewPos - viewPos);
float hitNdotV = clamp(dot(viewNormal, -hitDir), 0.0, 1.0);
float hitBackFace = smoothstep(-0.15, 0.3, hitNdotV);
float reflectivity = 1.0 - roughness;
#ifdef _CPostprocess
float intensity = pow(reflectivity, PPComp10.x) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((PPComp9.z - length(viewPos - hitCoord)) * (1.0 / PPComp9.z), 0.0, 1.0) * coords.w;
float falloffExp = PPComp10.x;
float maxDist = PPComp9.z;
#else
float intensity = pow(reflectivity, ssrFalloffExp) * screenEdgeFactor * clamp(-reflected.z, 0.0, 1.0) * clamp((ssrSearchDist - length(viewPos - hitCoord)) * (1.0 / ssrSearchDist), 0.0, 1.0) * coords.w;
float falloffExp = ssrFalloffExp;
float maxDist = ssrSearchDist;
#endif
float distAttenuation = 1.0 - clamp(length(viewPos - hitCoord) / maxDist, 0.0, 1.0);
distAttenuation = pow(distAttenuation, 1.5);
float fresnel = pow(1.0 - NdotV, 5.0);
fresnel = mix(0.04, 1.0, fresnel);
float intensity = pow(reflectivity, falloffExp) * screenEdgeFactor
* smoothstep(0.0, 0.1, -reflected.z)
* distAttenuation
* hitBackFace
* coords.w;
intensity = clamp(intensity, 0.0, 1.0);
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb;
reflCol = clamp(reflCol, 0.0, 1.0);
fragColor.rgb = reflCol * intensity * 0.5;
fragColor.rgb = reflCol * intensity * mix(0.5, 1.0, fresnel);
}

View File

@ -22,6 +22,10 @@
"name": "cameraProj",
"link": "_cameraPlaneProj"
},
{
"name": "screenSize",
"link": "_screenSize"
},
{
"name": "PPComp9",
"link": "_PPComp9",

View File

@ -12,6 +12,7 @@ uniform sampler2D tex1;
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform sampler2D gbufferD1;
uniform sampler2D gbuffer1;
uniform sampler2D gbuffer_refraction; // ior\opacity
uniform mat4 P;
@ -26,7 +27,7 @@ vec3 hitCoord;
float depth;
const int numBinarySearchSteps = 7;
const int maxSteps = int(ceil(1.0 / ss_refractionRayStep) * ss_refractionSearchDist);
const int maxSteps = 50;
vec2 getProjectedCoord(const vec3 hit) {
vec4 projectedCoord = P * vec4(hit, 1.0);
@ -39,45 +40,60 @@ vec2 getProjectedCoord(const vec3 hit) {
}
float getDeltaDepth(const vec3 hit) {
depth = textureLod(gbufferD1, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
vec2 tc = getProjectedCoord(hit);
if (tc.x < 0.0 || tc.x > 1.0 || tc.y < 0.0 || tc.y > 1.0)
return -1.0;
depth = textureLod(gbufferD1, tc, 0.0).r * 2.0 - 1.0;
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
return viewPos.z - hit.z;
}
vec4 binarySearch(vec3 dir) {
vec4 binarySearch(vec3 dir, float stepSize) {
float ddepth;
for (int i = 0; i < numBinarySearchSteps; i++) {
dir *= 0.5;
hitCoord -= dir;
stepSize *= 0.5;
hitCoord -= dir * stepSize;
ddepth = getDeltaDepth(hitCoord);
if (ddepth < 0.0) hitCoord += dir;
if (ddepth < 0.0) hitCoord += dir * stepSize;
}
if (abs(ddepth) > ss_refractionSearchDist) return vec4(0.0);
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
if (abs(ddepth) > ss_refractionSearchDist * 0.005) return vec4(0.0);
vec2 hitTC = getProjectedCoord(hitCoord);
if (hitTC.x < 0.0 || hitTC.x > 1.0 || hitTC.y < 0.0 || hitTC.y > 1.0)
return vec4(0.0);
return vec4(hitTC, 0.0, 1.0);
}
vec4 rayCast(vec3 dir) {
float ddepth;
dir *= ss_refractionRayStep;
float stepSize = ss_refractionRayStep * max(1.0, -viewRay.z * 0.1);
vec3 startPos = hitCoord;
for (int i = 0; i < maxSteps; i++) {
hitCoord += dir;
ddepth = getDeltaDepth(hitCoord);
if (ddepth > 0.0) return binarySearch(dir);
hitCoord += dir * stepSize;
float dist = length(hitCoord - startPos);
if (dist > ss_refractionSearchDist) break;
float ddepth = getDeltaDepth(hitCoord);
if (ddepth > 0.0) return binarySearch(dir, stepSize);
stepSize *= 1.03;
}
return vec4(texCoord, 0.0, 0.0);
}
void main() {
vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0);
float ior = gr.x;
float ior = unpackIOR(gr.x);
float transmittance = gr.y;
float surfaceDepth = gr.z;
float d = surfaceDepth * 2.0 - 1.0;
vec4 sceneSample = textureLod(tex, texCoord, 0.0);
if (surfaceDepth == 0.0 || transmittance == 0.0 || ior == 1.0) {
if (surfaceDepth == 0.0 || surfaceDepth == 1.0) {
fragColor = sceneSample;
return;
}
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0);
if (transmittance == 0.0 || ior == 1.0) {
vec3 background = textureLod(tex1, texCoord, 0.0).rgb;
fragColor.rgb = sceneSample.rgb + background * (1.0 - sceneSample.a);
fragColor.rgb = g1.rgb + background * transmittance;
fragColor.a = 1.0;
return;
}
@ -96,18 +112,18 @@ void main() {
vec3 refracted = refract(incident, viewNormal, 1.0 / ior);
if (length(refracted) < 0.001) {
vec3 background = textureLod(tex1, texCoord, 0.0).rgb;
fragColor.rgb = sceneSample.rgb + background * (1.0 - sceneSample.a);
fragColor.rgb = g1.rgb + background * transmittance;
fragColor.a = 1.0;
return;
}
hitCoord = viewPos;
vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0;
vec3 dir = normalize(refracted);
vec4 coords = rayCast(dir);
vec2 screenEdge = smoothstep(0.0, 0.1, coords.xy) * smoothstep(0.0, 0.1, 1.0 - coords.xy);
float screenEdgeFactor = screenEdge.x * screenEdge.y;
vec2 screenEdge = smoothstep(0.0, 0.05, coords.xy) * smoothstep(0.0, 0.05, 1.0 - coords.xy);
float screenEdgeFactor = max(screenEdge.x * screenEdge.y, 0.05);
float refractivity = 1.0 - roughness;
float intensity = pow(refractivity, ss_refractionFalloffExp) * screenEdgeFactor * coords.w;
@ -118,6 +134,6 @@ void main() {
vec3 behindColor = mix(straightBackground, refractedBackground, intensity);
fragColor.rgb = sceneSample.rgb + behindColor * (1.0 - sceneSample.a);
fragColor.rgb = g1.rgb + behindColor * transmittance;
fragColor.a = 1.0;
}

View File

@ -40,100 +40,148 @@
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1;
uniform sampler2D tex;
uniform vec2 dir;
uniform vec2 cameraProj;
uniform mat4 projectionMatrix;
#ifdef _ExtBRDF
//!uniform vec4 materialParams[MAX_MATERIALS * 8];
#endif
in vec2 texCoord;
out vec4 fragColor;
const vec3 SKIN_SSS_RADIUS = vec3(4.8, 2.4, 1.5);
const float SSS_DISTANCE_SCALE = 0.001;
// TODO: finish the SSS
const float SSS_SCALE = 0.05;
const float DEPTH_THRESHOLD = 0.05;
// Temp hash func -
float hash13(vec3 p3) {
p3 = fract(p3 * vec3(0.1031, 0.1030, 0.0973));
p3 += dot(p3, p3.yzx + 33.33);
return fract((p3.x + p3.y) * p3.z);
}
vec4 SSSSBlur() {
const int SSSS_N_SAMPLES = 15;
vec4 SSSSBlur(vec3 sssRadius, float sssWeight) {
const int SSSS_N_SAMPLES = 11;
vec4 kernel[SSSS_N_SAMPLES];
kernel[0] = vec4(0.233, 0.455, 0.649, 0.0); // Center sample
kernel[1] = vec4(0.100, 0.336, 0.344, 0.37); // +0.37mm
kernel[2] = vec4(0.118, 0.198, 0.0, 0.97); // +0.97mm
kernel[3] = vec4(0.113, 0.007, 0.007, 1.93); // +1.93mm
kernel[4] = vec4(0.358, 0.004, 0.0, 3.87); // +3.87mm
kernel[5] = vec4(0.078, 0.0, 0.0, 6.53); // +6.53mm (red only)
kernel[6] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
kernel[7] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
kernel[8] = vec4(0.100, 0.336, 0.344, -0.37); // -0.37mm
kernel[9] = vec4(0.118, 0.198, 0.0, -0.97); // -0.97mm
kernel[10] = vec4(0.113, 0.007, 0.007, -1.93); // -1.93mm
kernel[11] = vec4(0.358, 0.004, 0.0, -3.87); // -3.87mm
kernel[12] = vec4(0.078, 0.0, 0.0, -6.53); // -6.53mm (red only)
kernel[13] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
kernel[14] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
vec4 colorM = textureLod(tex, texCoord, 0.0);
float depth = textureLod(gbufferD, texCoord, 0.0).r;
kernel[0] = vec4(0.233, 0.455, 0.649, 0.0); // Center sample
kernel[1] = vec4(0.100, 0.336, 0.344, 0.37); // +0.37
kernel[2] = vec4(0.118, 0.198, 0.0, 0.97); // +0.97
kernel[3] = vec4(0.113, 0.007, 0.007, 1.93); // +1.93
kernel[4] = vec4(0.358, 0.004, 0.0, 3.87); // +3.87
kernel[5] = vec4(0.078, 0.0, 0.0, 6.53); // +6.53 (red only)
kernel[6] = vec4(0.100, 0.336, 0.344, -0.37); // -0.37
kernel[7] = vec4(0.118, 0.198, 0.0, -0.97); // -0.97
kernel[8] = vec4(0.113, 0.007, 0.007, -1.93); // -1.93
kernel[9] = vec4(0.358, 0.004, 0.0, -3.87); // -3.87
kernel[10] = vec4(0.078, 0.0, 0.0, -6.53); // -6.53 (red only)
vec2 texSize = vec2(textureSize(tex, 0));
ivec2 texelCoord = ivec2(texCoord * texSize);
vec4 colorM = texelFetch(tex, texelCoord, 0);
vec3 albedo = texelFetch(gbuffer1, texelCoord, 0).rgb;
vec3 irradianceM = colorM.rgb / max(albedo, vec3(0.00001));
float depth = texelFetch(gbufferD, texelCoord, 0).r;
float depthM = cameraProj.y / (depth - cameraProj.x);
float distanceScale = 1.0 / max(depthM, 0.1);
vec2 finalStep = sssWidth * distanceScale * dir * SSS_DISTANCE_SCALE;
float blurWidth = max(max(sssRadius.r, sssRadius.g), sssRadius.b);
float projScale = dot(dir, vec2(projectionMatrix[0][0], projectionMatrix[1][1]));
vec2 finalStep = blurWidth * (1.0 / depthM) * dir * projScale * SSS_SCALE;
vec3 jitterSeed = vec3(texCoord.xy * 1000.0, fract(cameraProj.x * 0.0001));
float jitterOffset = (hash13(jitterSeed) * 2.0 - 1.0) * 0.15;
finalStep *= (1.0 + jitterOffset);
vec3 colorBlurred = vec3(0.0);
vec3 weightSum = vec3(0.0);
colorBlurred += colorM.rgb * kernel[0].rgb;
weightSum += kernel[0].rgb;
vec3 colorBlurred = irradianceM * kernel[0].rgb;
vec3 weightSum = kernel[0].rgb;
for (int i = 1; i < SSSS_N_SAMPLES; i++) {
float sampleJitter = hash13(vec3(texCoord.xy * 720.0, float(i) * 37.45)) * 0.1 - 0.05;
vec2 offset = texCoord + (kernel[i].a + sampleJitter) * finalStep;
vec4 color = textureLod(tex, offset, 0.0);
const float DEPTH_THRESHOLD = 0.05;
float sampleDepth = textureLod(gbufferD, offset, 0.0).r;
float sampleDepthM = cameraProj.y / (sampleDepth - cameraProj.x);
float depthDiff = abs(depthM - sampleDepthM);
float depthWeight = exp(-depthDiff * 10.0);
if (depthDiff > DEPTH_THRESHOLD) {
color.rgb = mix(colorM.rgb, color.rgb, depthWeight);
vec3 irradiance = irradianceM;
float s = 0.0;
if (all(greaterThanEqual(offset, vec2(0.0))) && all(lessThan(offset, vec2(1.0)))) {
ivec2 sampleTexel = ivec2(offset * texSize);
float sampleDepth = texelFetch(gbufferD, sampleTexel, 0).r;
float sampleDepthM = cameraProj.y / (sampleDepth - cameraProj.x);
float depthDiff = abs(depthM - sampleDepthM);
if (depthDiff < 1.0) {
vec4 sampleG0 = texelFetch(gbuffer0, sampleTexel, 0);
float sampleMetallic;
uint sampleMatid;
unpackFloatInt16(sampleG0.a, sampleMetallic, sampleMatid);
bool sampleIsSSS = false;
#ifdef _ExtBRDF
if (sampleMatid >= 3u && sampleMatid < uint(MAX_MATERIALS)) {
if (materialParams[sampleMatid * 8u + 3u].z > 0.0) sampleIsSSS = true;
}
#endif
if (sampleIsSSS) {
vec3 sampleColor = texelFetch(tex, sampleTexel, 0).rgb;
vec3 sampleAlbedo = texelFetch(gbuffer1, sampleTexel, 0).rgb;
irradiance = sampleColor / max(sampleAlbedo, vec3(0.00001));
}
if (depthDiff <= DEPTH_THRESHOLD) {
s = 1.0;
} else {
s = exp(-depthDiff * 10.0);
}
}
}
colorBlurred += color.rgb * kernel[i].rgb;
colorBlurred += kernel[i].rgb * mix(irradianceM, irradiance, s);
weightSum += kernel[i].rgb;
}
vec3 normalizedColor = colorBlurred / max(weightSum, vec3(0.00001));
vec3 normalizedIrradiance = colorBlurred / max(weightSum, vec3(0.00001));
float dither = hash13(vec3(texCoord * 1333.0, 0.0)) * 0.003 - 0.0015;
normalizedColor = max(normalizedColor + vec3(dither), vec3(0.0));
return vec4(normalizedColor, colorM.a);
normalizedIrradiance = max(normalizedIrradiance + vec3(dither), vec3(0.0));
vec3 blurredColor = normalizedIrradiance * albedo;
vec3 result = mix(colorM.rgb, blurredColor, sssWeight);
return vec4(result, colorM.a);
}
void main() {
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
vec2 texSize0 = vec2(textureSize(gbuffer0, 0));
ivec2 texelCoord0 = ivec2(texCoord * texSize0);
vec4 g0 = texelFetch(gbuffer0, texelCoord0, 0);
float metallic;
uint matid;
unpackFloatInt16(g0.a, metallic, matid);
if (matid == 2u) {
vec4 originalColor = textureLod(tex, texCoord, 0.0);
vec4 blurredColor = SSSSBlur();
vec4 sssContribution = blurredColor - originalColor;
vec4 combined = originalColor + max(vec4(0.0), sssContribution) * 0.8;
fragColor = max(vec4(0.0), min(combined, vec4(10.0)));
bool applySSS = false;
vec3 sssRadius = vec3(1.0);
float sssWeight = 1.0;
vec4 matp0, matp1, matp2, matp3, matp4, matp5, matp6, matp7;
#ifdef _ExtBRDF
if (matid >= 3u && matid < uint(MAX_MATERIALS)) {
getMaterialParams(matid, matp0, matp1, matp2, matp3, matp4, matp5, matp6, matp7);
// matp3.z = subsurface, matp4.xyz = subsurfaceRadiusRGB, matp7.x = subsurfaceScale
if (matp3.z > 0.0) {
applySSS = true;
sssRadius = matp4.xyz * matp7.x;
sssWeight = matp3.z;
}
}
#endif
if (applySSS) {
fragColor = SSSSBlur(sssRadius, sssWeight);
} else {
fragColor = textureLod(tex, texCoord, 0.0);
vec2 texSizeMain = vec2(textureSize(tex, 0));
ivec2 texelCoordMain = ivec2(texCoord * texSizeMain);
fragColor = texelFetch(tex, texelCoordMain, 0);
}
}

View File

@ -13,6 +13,16 @@
{
"name": "cameraProj",
"link": "_cameraPlaneProj"
},
{
"name": "projectionMatrix",
"link": "_projectionMatrix"
},
{
"name": "materialParams",
"link": "_materialParams",
"type": "floats",
"ifdef": ["_ExtBRDF"]
}
],
"texture_params": [],
@ -32,6 +42,16 @@
{
"name": "cameraProj",
"link": "_cameraPlaneProj"
},
{
"name": "projectionMatrix",
"link": "_projectionMatrix"
},
{
"name": "materialParams",
"link": "_materialParams",
"type": "floats",
"ifdef": ["_ExtBRDF"]
}
],
"texture_params": [],

View File

@ -1,10 +1,30 @@
#ifndef _BRDF_GLSL_
#define _BRDF_GLSL_
#ifndef PI
#define PI 3.1415926535
#endif
#ifndef INV_PI
#define INV_PI 0.3183098861
#endif
#ifndef INV_TWO_PI
#define INV_TWO_PI 0.1591549430
#endif
#ifndef SCHLICK_A
#define SCHLICK_A -5.55473
#endif
#ifndef SCHLICK_B
#define SCHLICK_B -6.98316
#endif
#ifndef SRGB_GAMMA
#define SRGB_GAMMA 2.2
#endif
#define srgbToLinear(x) pow(x, vec3(SRGB_GAMMA))
// http://xlgames-inc.github.io/posts/improvedibl/
// http://blog.selfshadow.com/publications/s2013-shading-course/
vec3 f_schlick(const vec3 f0, const float vh) {
return f0 + (1.0 - f0) * exp2((-5.55473 * vh - 6.98316) * vh);
return f0 + (1.0 - f0) * exp2((SCHLICK_A * vh + SCHLICK_B) * vh);
}
float v_smithschlick(const float nl, const float nv, const float a) {
@ -31,7 +51,7 @@ float d_ggx(const float nh, const float a) {
float a2 = a * a;
float denom = nh * nh * (a2 - 1.0) + 1.0;
denom = max(denom * denom, 0.00006103515625 /* 2^-14 = smallest possible half float value, prevent div by zero */);
return a2 * (1.0 / 3.1415926535) / denom;
return a2 * INV_PI / denom;
}
vec3 specularBRDF(const vec3 f0, const float roughness, const float nl, const float nh, const float nv, const float vh) {
@ -44,11 +64,10 @@ vec3 specularBRDF(const vec3 f0, const float roughness, const float nl, const fl
// http://filmicworlds.com/blog/optimizing-ggx-shaders-with-dotlh/
vec3 specularBRDFb(const vec3 f0, const float roughness, const float dotNL, const float dotNH, const float dotLH) {
// D
const float pi = 3.1415926535;
float alpha = roughness * roughness;
float alphaSqr = alpha * alpha;
float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
float D = alphaSqr / (pi * denom * denom);
float D = alphaSqr / (PI * denom * denom);
// F
const float F_a = 1.0;
float F_b = pow(1.0 - dotLH, 5.0);
@ -65,21 +84,8 @@ vec3 specularBRDFb(const vec3 f0, const float roughness, const float dotNL, cons
return specular / 4.0; // TODO: get rid of / 4.0
}
vec3 orenNayarDiffuseBRDF(const vec3 albedo, const float roughness, const float nv, const float nl, const float vh) {
float a = roughness * roughness;
float s = a;
float s2 = s * s;
float vl = 2.0 * vh * vh - 1.0; // Double angle identity
float Cosri = vl - nv * nl;
float C1 = 1.0 - 0.5 * s2 / (s2 + 0.33);
float test = 1.0;
if (Cosri >= 0.0) test = (1.0 / (max(nl, nv)));
float C2 = 0.45 * s2 / (s2 + 0.09) * Cosri * test;
return albedo * max(0.0, nl) * (C1 + C2) * (1.0 + roughness * 0.5);
}
vec3 lambertDiffuseBRDF(const vec3 albedo, const float nl) {
return albedo * (1.0 / 3.1415926535) * nl;
return albedo * INV_PI * nl;
}
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
@ -95,24 +101,6 @@ float getMipFromRoughness(const float roughness, const float numMipmaps) {
return roughness * numMipmaps;
}
float wardSpecular(vec3 N, vec3 H, float dotNL, float dotNV, float dotNH, vec3 fiberDirection, float shinyParallel, float shinyPerpendicular) {
if(dotNL < 0.0 || dotNV < 0.0) {
return 0.0;
}
// fiberDirection - parse from rotation
// shinyParallel - roughness
// shinyPerpendicular - anisotropy
vec3 fiberParallel = normalize(fiberDirection);
vec3 fiberPerpendicular = normalize(cross(N, fiberDirection));
float dotXH = dot(fiberParallel, H);
float dotYH = dot(fiberPerpendicular, H);
const float PI = 3.1415926535;
float coeff = sqrt(dotNL/dotNV) / (4.0 * PI * shinyParallel * shinyPerpendicular);
float theta = (pow(dotXH/shinyParallel, 2.0) + pow(dotYH/shinyPerpendicular, 2.0)) / (1.0 + dotNH);
return clamp(coeff * exp(-2.0 * theta), 0.0, 1.0);
}
// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
// vec3 EnvBRDFApprox(vec3 SpecularColor, float Roughness, float NoV) {
// const vec4 c0 = { -1, -0.0275, -0.572, 0.022 };
@ -138,4 +126,207 @@ float D_Approx(const float Roughness, const float RoL) {
return rcp_a2 * exp2( c * RoL - c );
}
#ifdef _ClearCoat
float brdf_coatF0;
vec3 clearcoatBRDF(const float clearcoat, const float clearcoat_rough,
const float coat_ior, const vec3 coatN, const vec3 l, const vec3 v, const vec3 h) {
if (clearcoat <= 0.0) return vec3(0.0);
float cdotNL = max(0.0, dot(coatN, l));
float cdotNH = max(0.0, dot(coatN, h));
float cdotNV = max(0.0, dot(coatN, v));
float cdotVH = max(0.0, dot(v, h));
float a = clearcoat_rough * clearcoat_rough;
float F = brdf_coatF0 + (1.0 - brdf_coatF0) * exp2((SCHLICK_A * cdotVH + SCHLICK_B) * cdotVH);
float D = d_ggx(cdotNH, a);
float G = g2_approx(cdotNL, cdotNV, a);
return vec3(clearcoat * D * G * F / max(4.0 * cdotNV, 1e-5));
}
float coatAttenuation(const float clearcoat,
const float coat_ior, const vec3 coatN, const vec3 v) {
if (clearcoat <= 0.0) return 1.0;
float cdotNV = max(0.0, dot(coatN, v));
float F = brdf_coatF0 + (1.0 - brdf_coatF0) * exp2((SCHLICK_A * cdotNV + SCHLICK_B) * cdotNV);
return max(1.0 - F * clearcoat, 0.0);
}
vec3 coatTintAttenuation(const float clearcoat, const vec3 coat_tint, const vec3 coatN, const vec3 v) {
if (clearcoat <= 0.0) return vec3(1.0);
float cdotNV = max(0.0, dot(coatN, v));
float absorption = 1.0 / max(cdotNV, 0.3);
return mix(vec3(1.0), clamp(coat_tint, 0.0, 1.0), clamp(absorption * 0.2, 0.0, 1.0));
}
#endif
#ifdef _Sheen
float brdf_sheenAlbedo;
// based on Blender sheen model/Frostbite PBR
vec3 sheenBRDF(const float sheen, const float sheen_rough,
const vec3 sheen_tint, const float dotNL, const float dotNH, const float dotNV) {
if (sheen <= 0.0) return vec3(0.0);
float rough = clamp(sheen_rough, 1e-3, 1.0);
float a = rough * rough;
float sinNH2 = 1.0 - dotNH * dotNH;
float a2 = a * a;
float denom = 1.0 + a2 * sinNH2;
float D = (2.0 + a2) * sinNH2 * INV_TWO_PI / (denom * denom);
float V = 1.0 / (4.0 * dotNL * dotNV + 1e-5);
return sheen_tint * sheen * D * V * dotNL * brdf_sheenAlbedo;
}
float sheenAttenuation(const float sheen, const float sheen_rough,
const vec3 sheen_tint, const float dotNV) {
if (sheen <= 0.0) return 1.0;
float maxComp = sheen * max(max(sheen_tint.r, sheen_tint.g), sheen_tint.b) * brdf_sheenAlbedo;
return max(1.0 - maxComp, 0.0);
}
#endif
#ifdef _Anisotropy
// anisotropic GGX Burley 2012
vec3 anisotropicBRDF(const vec3 f0, const float roughness, const float anisotropy,
const float aniso_rot, const vec3 tangent, const vec3 bitangent,
const vec3 n, const vec3 l, const vec3 v,
const float dotNL, const float dotNV) {
if (abs(anisotropy) <= 0.001) return vec3(0.0);
float rot = aniso_rot * PI * 2.0;
float cr = cos(rot);
float sr = sin(rot);
vec3 t = normalize(tangent * cr + bitangent * sr);
vec3 b = normalize(bitangent * cr - tangent * sr);
float aniso_abs = abs(anisotropy);
float at = max(roughness * (1.0 + aniso_abs), 1e-5);
float ab = max(roughness * (1.0 - aniso_abs), 1e-5);
if (anisotropy < 0.0) { vec3 tmp = t; t = b; b = tmp; }
float at2 = at * at;
float ab2 = ab * ab;
vec3 h = normalize(l + v);
float dotTH = dot(t, h);
float dotBH = dot(b, h);
float dotTV = dot(t, v);
float dotBV = dot(b, v);
float dotTL = dot(t, l);
float dotBL = dot(b, l);
float denom = max(dotTH * dotTH / at2 + dotBH * dotBH / ab2, 1e-7);
float D = INV_PI / (at * ab * denom * denom);
float V = 1.0 / max(dotNL * (dotTL / at + dotBL / ab) * (dotTV / at + dotBV / ab), 1e-5);
float dotVH = max(dot(v, h), 0.0);
vec3 F = f_schlick(f0, dotVH);
return D * V * F / max(4.0 * dotNV, 1e-5);
}
#endif
#ifdef _Transmission
float brdf_transmissionF0;
// Blenders microfacet glass/refraction model
vec3 transmissionBRDF(const vec3 albedo, const float transmission,
const float trans_rough, const float ior, const float thin_wall,
const float dotNL, const float dotNV, const float dotVH) {
if (transmission <= 0.0) return vec3(0.0);
float F = brdf_transmissionF0 + (1.0 - brdf_transmissionF0) * exp2((SCHLICK_A * dotVH + SCHLICK_B) * dotVH);
float transmittance = 1.0 - F;
if (thin_wall > 0.5) {
return albedo * transmission * transmittance * dotNL;
}
float a = trans_rough * trans_rough;
float rough_atten = min(mix(1.0, 1.0 / max(dotNV, 0.1), a), 4.0);
return albedo * transmission * transmittance * rough_atten * dotNL;
}
#endif
#ifdef _ExtBRDF
float brdf_sheenWeight = 1.0;
float brdf_coatWeight = 1.0;
vec3 brdf_coatTintAbsorb = vec3(1.0);
vec3 applyExtBRDFLayers(
const vec3 direct,
const vec3 albedo,
const vec3 f0,
const float roughness,
const float dotNL, const float dotNV, const float dotNH, const float dotVH,
const vec3 n, const vec3 l, const vec3 v, const vec3 h,
#ifdef _ClearCoat
const float clearcoat, const float clearcoatRough, const float coatIOR,
const vec3 coatTint, const vec3 coatN,
#endif
#ifdef _Sheen
const float sheen, const float sheenRough, const vec3 sheenTint,
#endif
#ifdef _Transmission
const float transmission, const float transRough, const float ior, const float thinWall,
#endif
out float layerWeight
) {
float sheenWeight = brdf_sheenWeight;
float coatWeight = brdf_coatWeight;
#ifdef _Sheen
vec3 sheenContrib = sheenBRDF(sheen, sheenRough, sheenTint, dotNL, dotNH, dotNV);
#endif
#ifdef _ClearCoat
vec3 coatContrib = clearcoatBRDF(clearcoat, clearcoatRough, coatIOR, coatN, l, v, h);
#endif
layerWeight = sheenWeight * coatWeight;
vec3 result = direct * layerWeight;
#ifdef _Transmission
result += transmissionBRDF(albedo, transmission, transRough, ior, thinWall, dotNL, dotNV, dotVH) * layerWeight;
#endif
#ifdef _ClearCoat
result *= brdf_coatTintAbsorb;
result += coatContrib * sheenWeight;
#endif
#ifdef _Sheen
result += sheenContrib;
#endif
return result;
}
#endif
#ifdef _ClearCoat
float coatIBLFresnel(const float clearcoat, const float coat_ior,
const float dotNV_coat) {
if (clearcoat <= 0.0) return 0.0;
float F = brdf_coatF0 + (1.0 - brdf_coatF0) * exp2((SCHLICK_A * dotNV_coat + SCHLICK_B) * dotNV_coat);
return F * clearcoat;
}
#endif
#ifdef _Sheen
float sheenIBLAlbedo(const float sheen, const float sheen_rough,
const float dotNV) {
if (sheen <= 0.0) return 0.0;
float rough = clamp(sheen_rough, 1e-3, 1.0);
return sheen * (1.0 - 0.5 * rough) * mix(1.0, dotNV, 0.5);
}
#endif
#ifdef _Anisotropy
vec3 anisotropicIBLDirection(const vec3 n, const vec3 v, const vec3 tangent,
const float anisotropy, const float roughness) {
if (abs(anisotropy) <= 0.001 || dot(tangent, tangent) < 0.001)
return reflect(-v, n);
vec3 bitangent = normalize(cross(n, tangent));
vec3 r = reflect(-v, n);
float aniso_abs = abs(anisotropy);
vec3 stretchDir = anisotropy > 0.0 ? tangent : bitangent;
float stretchAmt = aniso_abs * roughness;
return normalize(r + stretchDir * stretchAmt * dot(r, stretchDir) * 0.5);
}
#endif
#ifdef _Transmission
float transmissionIBLFresnel(const float ior, const float dotNV) {
return brdf_transmissionF0 + (1.0 - brdf_transmissionF0) * exp2((SCHLICK_A * dotNV + SCHLICK_B) * dotNV);
}
vec3 transmissionIBLDirection(const vec3 n, const vec3 v, const float ior) {
float eta = 1.0 / ior;
vec3 refrDir = refract(-v, n, eta);
if (dot(refrDir, refrDir) < 0.001) {
refrDir = reflect(-v, n);
}
return refrDir;
}
#endif
#endif

View File

@ -34,17 +34,19 @@ THE SOFTWARE.
// https://research.nvidia.com/sites/default/files/publications/GIVoxels-pg2011-authors.pdf
const float MAX_DISTANCE = voxelgiRange;
const int MAX_CONE_STEPS = 32;
#ifdef _VoxelGI
uniform sampler3D dummy;
vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCount * 10], const float clipmap_index, const float step_dist, const int precomputed_direction, const vec3 face_offset, const vec3 direction_weight) {
vec4 col = vec4(0.0);
vec3 tc = (P - 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);
int base = int(clipmap_index * 10);
float voxelSize = float(clipmaps[base]);
vec3 tc = (P - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
vec3 half_texel = vec3(0.5) / voxelgiResolution;
tc = tc * 0.5 + 0.5;
tc = clamp(tc, half_texel, 1.0 - half_texel);
tc.x = (tc.x + precomputed_direction) / (6 + DIFFUSE_CONE_COUNT);
tc.x = (tc.x + precomputed_direction) / (6 + diffuseConeCount);
tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
if (precomputed_direction == 0) {
@ -55,7 +57,7 @@ vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCo
else
col = textureLod(voxels, tc, 0);
col *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
col *= step_dist / voxelSize;
return col;
}
@ -64,11 +66,13 @@ vec4 sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCo
#ifdef _VoxelAOvar
float sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapCount * 10], const float clipmap_index, const float step_dist, const int precomputed_direction, const vec3 face_offset, const vec3 direction_weight) {
float opac = 0.0;
vec3 tc = (P - 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);
int base = int(clipmap_index * 10);
float voxelSize = float(clipmaps[base]);
vec3 tc = (P - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
vec3 half_texel = vec3(0.5) / voxelgiResolution;
tc = tc * 0.5 + 0.5;
tc = clamp(tc, half_texel, 1.0 - half_texel);
tc.x = (tc.x + precomputed_direction) / (6 + DIFFUSE_CONE_COUNT);
tc.x = (tc.x + precomputed_direction) / (6 + diffuseConeCount);
tc.y = (tc.y + clipmap_index) / voxelgiClipmapCount;
if (precomputed_direction == 0) {
@ -79,7 +83,7 @@ float sampleVoxel(sampler3D voxels, vec3 P, const float clipmaps[voxelgiClipmapC
else
opac = textureLod(voxels, tc, 0).r;
opac *= step_dist / float(clipmaps[int(clipmap_index * 10)]);
opac *= step_dist / voxelSize;
return opac;
}
@ -92,7 +96,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
float dist = voxelSize0;
float step_dist = dist;
vec3 samplePos;
vec3 start_pos = origin + n * voxelSize0;
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
int clipmap_index0 = 0;
vec3 aniso_direction = -dir;
@ -100,20 +104,24 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
aniso_direction.x > 0.0 ? 0.0 : 1.0,
aniso_direction.y > 0.0 ? 2.0 : 3.0,
aniso_direction.z > 0.0 ? 4.0 : 5.0
) / (6 + DIFFUSE_CONE_COUNT);
) / (6 + diffuseConeCount);
vec3 direction_weight = abs(dir);
float coneCoefficient = 2.0 * tan(aperture * 0.5);
while (sampleCol.a < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
int steps = 0;
while (sampleCol.a < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
vec4 mipSample = vec4(0.0);
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);
int base = int(clipmap_index * 10);
float voxelSize = float(clipmaps[base]);
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
samplePos = samplePos * 0.5 + 0.5;
if (any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0)))) {
@ -121,19 +129,26 @@ 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.05 && 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);
int baseNext = int((clipmap_index + 1.0) * 10);
float voxelSizeCoarse = float(clipmaps[baseNext]);
mipSampleNext *= voxelSizeCoarse / voxelSize;
mipSample = mix(mipSample, mipSampleNext, totalBlend);
}
sampleCol += (1.0 - sampleCol.a) * mipSample;
float stepSizeCurrent = step_size;
if (use_sdf) {
// half texel correction is applied to avoid sampling over current clipmap:
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel);
tc0.y = (tc0.y + clipmap_index) / voxelgiClipmapCount; // remap into clipmap
float sdf = textureLod(voxelsSDF, tc0, 0).r;
@ -141,6 +156,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
}
step_dist = diam * stepSizeCurrent;
dist += step_dist;
steps++;
}
return sampleCol;
}
@ -148,18 +164,17 @@ 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];
for (int i = 0; i < diffuseConeCount; ++i) {
vec3 coneDir = diffuseConeDirections[i];
const float cosTheta = dot(normal, coneDir);
if (cosTheta <= 0)
continue;
int precomputed_direction = 6 + i;
amount += traceCone(voxels, dummy, origin, normal, coneDir, precomputed_direction, false, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta;
amount += traceCone(voxels, voxels, origin, normal, coneDir, precomputed_direction, false, diffuseConeAperture, 1.0, clipmaps) * cosTheta;
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);
@ -186,7 +201,7 @@ vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sam
amount.rgb = max(vec3(0.0), amount.rgb);
amount.a = clamp(amount.a, 0.0, 1.0);
return amount * voxelgiOcc;
return amount * voxelgiOcc * voxelgiRefr;
}
#endif
@ -197,7 +212,7 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
float dist = voxelSize0;
float step_dist = dist;
vec3 samplePos;
vec3 start_pos = origin + n * voxelSize0;
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
int clipmap_index0 = 0;
vec3 aniso_direction = -dir;
@ -205,20 +220,23 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
aniso_direction.x > 0.0 ? 0.0 : 1.0,
aniso_direction.y > 0.0 ? 2.0 : 3.0,
aniso_direction.z > 0.0 ? 4.0 : 5.0
) / (6 + DIFFUSE_CONE_COUNT);
) / (6 + diffuseConeCount);
vec3 direction_weight = abs(dir);
float coneCoefficient = 2.0 * tan(aperture * 0.5);
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
int steps = 0;
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
float mipSample = 0.0;
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);
int base = int(clipmap_index * 10);
float voxelSize = float(clipmaps[base]);
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
samplePos = samplePos * 0.5 + 0.5;
if ((any(notEqual(clamp(samplePos, 0.0, 1.0), samplePos)))) {
@ -226,17 +244,27 @@ 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.05 && 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);
int baseNext = int((clipmap_index + 1.0) * 10);
float voxelSizeCoarse = float(clipmaps[baseNext]);
mipSampleNext *= voxelSizeCoarse / voxelSize;
mipSample = mix(mipSample, mipSampleNext, totalBlend);
}
sampleCol += (1.0 - sampleCol) * mipSample;
step_dist = diam * step_size;
dist += step_dist;
steps++;
}
return sampleCol;
}
@ -245,18 +273,18 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
float sum = 0.0;
float amount = 0.0;
for (int i = 0; i < DIFFUSE_CONE_COUNT; i++) {
vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i];
for (int i = 0; i < diffuseConeCount; i++) {
vec3 coneDir = diffuseConeDirections[i];
int precomputed_direction = 6 + i;
const float cosTheta = dot(normal, coneDir);
if (cosTheta <= 0)
continue;
amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, DIFFUSE_CONE_APERTURE, 1.0, clipmaps) * cosTheta;
amount += traceConeAO(voxels, origin, normal, coneDir, precomputed_direction, diffuseConeAperture, 1.0, clipmaps) * cosTheta;
sum += cosTheta;
}
amount /= sum;
amount /= max(sum, 0.0001);
amount = clamp(amount, 0.0, 1.0);
return amount * voxelgiOcc;
return amount;
}
#endif
@ -267,7 +295,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
float dist = voxelSize0;
float step_dist = dist;
vec3 samplePos;
vec3 start_pos = origin + n * voxelSize0;
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
int clipmap_index0 = 0;
vec3 aniso_direction = -dir;
@ -275,19 +303,23 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
aniso_direction.x > 0.0 ? 0.0 : 1.0,
aniso_direction.y > 0.0 ? 2.0 : 3.0,
aniso_direction.z > 0.0 ? 4.0 : 5.0
) / (6 + DIFFUSE_CONE_COUNT);
) / (6 + diffuseConeCount);
vec3 direction_weight = abs(dir);
float coneCoefficient = 2.0 * tan(aperture * 0.5);
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount) {
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
int steps = 0;
while (sampleCol < 1.0 && dist < MAX_DISTANCE && clipmap_index0 < voxelgiClipmapCount && steps < MAX_CONE_STEPS) {
float mipSample = 0.0;
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);
int base = int(clipmap_index * 10);
float voxelSize = float(clipmaps[base]);
samplePos = (p0 - vec3(clipmaps[base + 4], clipmaps[base + 5], clipmaps[base + 6])) / (voxelSize * voxelgiResolution);
samplePos = samplePos * 0.5 + 0.5;
if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) {
@ -295,27 +327,34 @@ 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.05 && clipmap_index < voxelgiClipmapCount - 1) {
int baseNext = int((clipmap_index + 1.0) * 10);
float voxelSizeCoarse = float(clipmaps[baseNext]);
float scaleRatio = voxelSizeCoarse / voxelSize;
#ifdef _VoxelAOvar
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight);
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight) * scaleRatio;
#else
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a;
float mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, 0, face_offset, direction_weight).a * scaleRatio;
#endif
mipSample = mix(mipSample, mipSampleNext, clipmap_blend);
mipSample = mix(mipSample, mipSampleNext, totalBlend);
}
sampleCol += (1.0 - sampleCol) * mipSample;
float stepSizeCurrent = step_size;
// half texel correction is applied to avoid sampling over current clipmap:
const vec3 half_texel = vec3(0.5) / voxelgiResolution;
vec3 tc0 = clamp(samplePos, half_texel, 1 - half_texel);
tc0.y = (tc0.y + clipmap_index) / voxelgiClipmapCount; // remap into clipmap
float sdf = textureLod(voxelsSDF, tc0, 0.0).r;
@ -323,6 +362,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
step_dist = diam * stepSizeCurrent;
dist += step_dist;
steps++;
}
return sampleCol;
}
@ -330,7 +370,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, SHADOW_CONE_APERTURE, voxelgiStep, clipmaps);
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, voxelgiAperture, voxelgiStep, clipmaps);
amount = clamp(amount, 0.0, 1.0);
return amount * voxelgiOcc;
}

View File

@ -20,46 +20,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
const int DIFFUSE_CONE_COUNT = 16;
const float diffuseConeAperture = radians(39.0);
const float SHADOW_CONE_APERTURE = radians(15.0);
const float DIFFUSE_CONE_APERTURE = 0.872665;
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
const vec3 diffuseConeDirections[16] = vec3[](
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

View File

@ -170,4 +170,88 @@ void unpackFloatInt16(float val, out float f, out uint i) {
f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat;
}
#ifdef _ExtBRDF
// extended material parameters by material slot ID returns vec4s (28 floats) of extended BRDF parameters
void getMaterialParams(uint matid, out vec4 p0, out vec4 p1, out vec4 p2, out vec4 p3,
out vec4 p4, out vec4 p5, out vec4 p6, out vec4 p7) {
uint base = matid * 8u;
#if defined(_Anisotropy) || defined(_Sheen)
p0 = materialParams[base];
#else
p0 = vec4(0.0);
#endif
#if defined(_ClearCoat)
p1 = materialParams[base + 1u];
#else
p1 = vec4(0.0);
#endif
#if defined(_ClearCoat) || defined(_Transmission)
p2 = materialParams[base + 2u];
#else
p2 = vec4(0.0);
#endif
#if defined(_Transmission) || defined(_SSS)
p3 = materialParams[base + 3u];
#else
p3 = vec4(0.0);
#endif
#if defined(_SSS)
p4 = materialParams[base + 4u];
#else
p4 = vec4(0.0);
#endif
#if defined(_Sheen) || defined(_SSS)
p5 = materialParams[base + 5u];
#else
p5 = vec4(0.0);
#endif
#if defined(_ExtBRDF)
p6 = materialParams[base + 6u];
#else
p6 = vec4(0.0);
#endif
#if defined(_SSS)
p7 = materialParams[base + 7u];
#else
p7 = vec4(0.0);
#endif
}
#endif
float packIOR(float ior) {
return clamp((ior - 1.0) / 1.5, 0.0, 1.0);
}
float unpackIOR(float packed) {
return packed * 1.5 + 1.0;
}
#ifndef PI
#define PI 3.1415926535
#endif
#ifndef PI2
#define PI2 6.2831853071
#endif
float encodeTangent(vec3 tangent, vec3 normal) {
if (length(tangent) < 0.5) return -1.0;
vec3 t = normalize(tangent);
vec3 n = normalize(normal);
vec3 ref = abs(n.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
vec3 r = normalize(ref - n * dot(ref, n));
vec3 b = cross(n, r);
float angle = atan(dot(t, b), dot(t, r));
return (angle / (2.0 * PI) + 0.5);
}
vec3 decodeTangent(float enc, vec3 normal) {
if (enc < 0.0) return vec3(1.0, 0.0, 0.0);
vec3 n = normalize(normal);
vec3 ref = abs(n.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
vec3 r = normalize(ref - n * dot(ref, n));
vec3 b = cross(n, r);
float angle = (enc - 0.5) * 2.0 * PI;
return normalize(r * cos(angle) + b * sin(angle));
}
#endif

View File

@ -3,7 +3,9 @@ uniform sampler2D texIES;
float iesAttenuation(vec3 l) {
const float PI = 3.1415926535;
#ifndef PI
#define PI 3.1415926535
#endif
// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
// Sample direction into light space
// vec3 iesSampleDirection = mul(light.worldToLight , -L);

View File

@ -51,7 +51,9 @@
//!uniform sampler2D shadowMapAtlasTransparent;
#endif
#endif
#ifndef _SinglePoint
uniform vec2 lightProj;
#endif
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasPoint;
@ -92,7 +94,6 @@ uniform vec3 lightArea3;
uniform sampler2D sltcMat;
uniform sampler2D sltcMag;
#ifdef _ShadowMap
#ifndef _Spot
#ifdef _SinglePoint
uniform sampler2DShadow shadowMapSpot[1];
#ifdef _ShadowMapTransparent
@ -100,18 +101,10 @@ uniform sampler2D sltcMag;
#endif
uniform mat4 LWVPSpotArray[1];
#endif
#ifdef _Clusters
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
#endif
uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif
#endif
#endif
#endif
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
vec3 sampleLightCore(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap
, int index, float bias, bool receiveShadow
@ -122,23 +115,34 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
#ifdef _VoxelShadow
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity
#ifdef _ClearCoat
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint, vec3 coatN
#endif
#ifdef _MicroShadowing
, float occ
#ifdef _Sheen
, float sheen, float sheenRough, vec3 sheenTint
#endif
#ifdef _SSRS
, sampler2D gbufferD, mat4 invVP, vec3 eye
#ifdef _Anisotropy
, float anisotropy, float anisoRot, vec3 tangent
#endif
#ifdef _SSS
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
#endif
#ifdef _Transmission
, float transmission, float transRough, float ior, float thinWall
#endif
, out vec3 l_out
) {
vec3 ld = lp - p;
vec3 l = normalize(ld);
float dist = length(ld);
vec3 l = ld / dist;
vec3 h = normalize(v + l);
float dotNH = max(0.0, dot(n, h));
float dotVH = max(0.0, dot(v, h));
float dotNL = max(0.0, dot(n, l));
#ifdef _VoxelPass
vec3 direct = vec3(dotNL);
#else
#ifdef _LTC
float theta = acos(dotNV);
vec2 tuv = vec2(rough, theta / (0.5 * PI));
@ -153,35 +157,49 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
#else
#ifdef _Anisotropy
vec3 direct;
if (abs(anisotropy) > 0.001 && dot(tangent, tangent) > 0.001) {
vec3 bitangent = normalize(cross(n, tangent));
direct = lambertDiffuseBRDF(albedo, dotNL) +
anisotropicBRDF(f0, rough, anisotropy, anisoRot,
tangent, bitangent, n, l, v, dotNL, dotNV) * spec;
} else {
direct = lambertDiffuseBRDF(albedo, dotNL) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
}
#else
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
#endif
#endif
direct *= attenuate(distance(p, lp));
// before attenuate/shadow so everything is properly shadowed in one pass
#ifdef _ExtBRDF
float layerWeight;
direct = applyExtBRDFLayers(direct, albedo, f0, rough,
dotNL, dotNV, dotNH, dotVH, n, l, v, h
#ifdef _ClearCoat
, clearcoat, clearcoatRough, coatIOR, coatTint, coatN
#endif
#ifdef _Sheen
, sheen, sheenRough, sheenTint
#endif
#ifdef _Transmission
, transmission, transRough, ior, thinWall
#endif
, layerWeight);
#endif
#endif
direct *= attenuate(dist);
direct *= min(lightCol, vec3(100.0));
#ifdef _MicroShadowing
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
#endif
#ifdef _SSRS
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
#endif
#ifdef _VoxelShadow
vec3 lightDir = l;
#ifdef _Spot
if (isSpot)
lightDir = spotDir;
#endif
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;
#endif
#ifdef _LTC
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
@ -193,7 +211,29 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
);
#endif
#ifdef _Clusters
vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas
tileBounds = tileBoundsSpotArray[index];
direct *= shadowTest(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
#ifndef _SingleAtlas
shadowMapAtlasSpot
#else
shadowMapAtlas
#endif
#endif
, lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#else
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
@ -231,8 +271,10 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#endif
);
#endif
#endif
}
#endif
l_out = l;
return direct;
#endif
@ -257,25 +299,26 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _Clusters
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas
direct *= shadowTest(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
#ifndef _SingleAtlas
shadowMapAtlasSpot
#else
shadowMapAtlas
#endif
#endif
, lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
tileBounds = tileBoundsSpotArray[index];
direct *= shadowTest(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
#ifndef _SingleAtlas
shadowMapAtlasSpot
#else
shadowMapAtlas
#endif
#endif
, lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#else
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
@ -317,6 +360,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#endif
}
#endif
l_out = l;
return direct;
}
#endif
@ -403,9 +447,157 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
}
#endif
l_out = l;
return direct;
}
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap
, int index, float bias, bool receiveShadow
#ifdef _ShadowMapTransparent
, bool transparent
#endif
#endif
#ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
#ifdef _VoxelShadow
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity
#endif
#ifdef _MicroShadowing
, float occ
#endif
#ifdef _SSRS
, sampler2D gbufferD, mat4 invVP, vec3 eye
#endif
#ifdef _ClearCoat
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint, vec3 coatN
#endif
#ifdef _Sheen
, float sheen, float sheenRough, vec3 sheenTint
#endif
#ifdef _Anisotropy
, float anisotropy, float anisoRot, vec3 tangent
#endif
#ifdef _SSS
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
#endif
#ifdef _Transmission
, float transmission, float transRough, float ior, float thinWall
#endif
) {
vec3 l;
vec3 direct = sampleLightCore(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
#ifdef _ShadowMap
, index, bias, receiveShadow
#ifdef _ShadowMapTransparent
, transparent
#endif
#endif
#ifdef _Spot
, isSpot, spotSize, spotBlend, spotDir, scale, right
#endif
#ifdef _ClearCoat
, clearcoat, clearcoatRough, coatIOR, coatTint, coatN
#endif
#ifdef _Sheen
, sheen, sheenRough, sheenTint
#endif
#ifdef _Anisotropy
, anisotropy, anisoRot, tangent
#endif
#ifdef _SSS
, subsurface, sssColor, sssRadius, sssAnisotropy
#endif
#ifdef _Transmission
, transmission, transRough, ior, thinWall
#endif
, l);
float dotNL = max(0.0, dot(n, l));
#ifdef _MicroShadowing
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
#endif
#ifdef _SSRS
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
#endif
#ifdef _VoxelShadow
vec3 lightDir = l;
#ifdef _Spot
if (isSpot)
lightDir = spotDir;
#endif
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;
#endif
return direct;
}
// Backward-compatible overload for generated shaders that don't pass extended BRDF params
#ifdef _ExtBRDF
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap
, int index, float bias, bool receiveShadow
#ifdef _ShadowMapTransparent
, bool transparent
#endif
#endif
#ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
#ifdef _VoxelShadow
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity
#endif
#ifdef _MicroShadowing
, float occ
#endif
#ifdef _SSRS
, sampler2D gbufferD, mat4 invVP, vec3 eye
#endif
) {
return sampleLight(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
#ifdef _ShadowMap
, index, bias, receiveShadow
#ifdef _ShadowMapTransparent
, transparent
#endif
#endif
#ifdef _Spot
, isSpot, spotSize, spotBlend, spotDir, scale, right
#endif
#ifdef _VoxelShadow
, voxels, voxelsSDF, clipmaps, velocity
#endif
#ifdef _MicroShadowing
, occ
#endif
#ifdef _SSRS
, gbufferD, invVP, eye
#endif
#ifdef _ClearCoat
, 0.0, 0.0, 1.5, vec3(1.0), n
#endif
#ifdef _Sheen
, 0.0, 0.0, vec3(1.0)
#endif
#ifdef _Anisotropy
, 0.0, 0.0, vec3(0.0)
#endif
#ifdef _SSS
, 0.0, vec3(0.0), vec3(0.0), 0.0
#endif
#ifdef _Transmission
, 0.0, 0.0, 1.45, 1.0
#endif
);
}
#endif // _ExtBRDF
#ifdef _VoxelGI
vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
@ -418,263 +610,94 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
#ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
) {
vec3 ld = lp - p;
vec3 l = normalize(ld);
vec3 h = normalize(v + l);
float dotNH = max(0.0, dot(n, h));
float dotVH = max(0.0, dot(v, h));
float dotNL = max(0.0, dot(n, l));
#ifdef _LTC
float theta = acos(dotNV);
vec2 tuv = vec2(rough, theta / (0.5 * PI));
tuv = tuv * LUT_SCALE + LUT_BIAS;
vec4 t = textureLod(sltcMat, tuv, 0.0);
mat3 invM = mat3(
vec3(1.0, 0.0, t.y),
vec3(0.0, t.z, 0.0),
vec3(t.w, 0.0, t.x));
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
#else
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
#ifdef _ClearCoat
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint, vec3 coatN
#endif
direct *= attenuate(distance(p, lp));
// CRITICAL: Clamp light color to prevent extreme HDR values causing white sphere artifacts
direct *= min(lightCol, vec3(100.0));
#ifdef _LTC
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#ifdef _Clusters
vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0);
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= shadowTest(shadowMapSpot[1],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[1],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[2],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[3],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
}
#ifdef _Sheen
, float sheen, float sheenRough, vec3 sheenTint
#endif
return direct;
#ifdef _Anisotropy
, float anisotropy, float anisoRot, vec3 tangent
#endif
#ifdef _Spot
if (isSpot) {
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
#ifdef _SSS
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
#endif
#ifdef _Transmission
, float transmission, float transRough, float ior, float thinWall
#endif
) {
vec3 l;
return sampleLightCore(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#ifdef _Clusters
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas
direct *= shadowTest(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
#ifndef _SingleAtlas
shadowMapAtlasSpot
#else
shadowMapAtlas
#endif
#endif
, lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#else
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= shadowTest(shadowMapSpot[1],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[1],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[2],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[3],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#endif
}
, index, bias, receiveShadow
#ifdef _ShadowMapTransparent
, transparent
#endif
return direct;
}
#endif
#ifdef _LightIES
direct *= iesAttenuation(-l);
#endif
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
#ifndef _Spot
direct *= PCFCube(shadowMapPoint[0],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[0],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#endif
#ifdef _Clusters
#ifdef _ShadowMapAtlas
direct *= PCFFakeCube(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
#ifndef _SingleAtlas
shadowMapAtlasPoint
#else
shadowMapAtlas
#endif
#endif
, ld, -l, bias, lightProj, n, index
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#else
if (index == 0) direct *= PCFCube(shadowMapPoint[0],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[0],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[1],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[2],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[3],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#endif
}
#endif
return direct;
#endif
#ifdef _Spot
, isSpot, spotSize, spotBlend, spotDir, scale, right
#endif
#ifdef _ClearCoat
, clearcoat, clearcoatRough, coatIOR, coatTint, coatN
#endif
#ifdef _Sheen
, sheen, sheenRough, sheenTint
#endif
#ifdef _Anisotropy
, anisotropy, anisoRot, tangent
#endif
#ifdef _SSS
, subsurface, sssColor, sssRadius, sssAnisotropy
#endif
#ifdef _Transmission
, transmission, transRough, ior, thinWall
#endif
, l);
}
// Backward-compatible overload for generated shaders that don't pass extended BRDF params
#ifdef _ExtBRDF
vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap
, int index, float bias, bool receiveShadow
#ifdef _ShadowMapTransparent
, bool transparent
#endif
#endif
#ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
) {
vec3 l;
return sampleLightCore(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
#ifdef _ShadowMap
, index, bias, receiveShadow
#ifdef _ShadowMapTransparent
, transparent
#endif
#endif
#ifdef _Spot
, isSpot, spotSize, spotBlend, spotDir, scale, right
#endif
#ifdef _ClearCoat
, 0.0, 0.0, 1.5, vec3(1.0), n
#endif
#ifdef _Sheen
, 0.0, 0.0, vec3(1.0)
#endif
#ifdef _Anisotropy
, 0.0, 0.0, vec3(0.0)
#endif
#ifdef _SSS
, 0.0, vec3(0.0), vec3(0.0), 0.0
#endif
#ifdef _Transmission
, 0.0, 0.0, 1.45, 1.0
#endif
, l);
}
#endif // _ExtBRDF
#endif
#endif

View File

@ -14,7 +14,7 @@
#ifdef _SinglePoint
#ifdef _Spot
uniform sampler2DShadow shadowMapSpot[1];
uniform mat4 LWVPSpot[1];
uniform mat4 LWVPSpotArray[1];
#else
uniform samplerCubeShadow shadowMapPoint[1];
uniform vec2 lightProj;
@ -24,7 +24,9 @@
#ifdef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlas;
#endif
#ifndef _SinglePoint
uniform vec2 lightProj;
#endif
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasPoint;
@ -53,19 +55,64 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _Spot
, bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
#ifdef _ClearCoat
, float clearcoat, float clearcoatRough, float coatIOR, vec3 coatTint, vec3 coatN
#endif
#ifdef _Sheen
, float sheen, float sheenRough, vec3 sheenTint
#endif
#ifdef _Anisotropy
, float anisotropy, float anisoRot, vec3 tangent
#endif
#ifdef _SSS
, float subsurface, vec3 sssColor, vec3 sssRadius, float sssAnisotropy
#endif
#ifdef _Transmission
, float transmission, float transRough, float ior, float thinWall
#endif
) {
vec3 ld = lp - p;
vec3 l = normalize(ld);
float dist = length(ld);
vec3 l = ld / dist;
vec3 h = normalize(v + l);
float dotNH = max(0.0, dot(n, h));
float dotVH = max(0.0, dot(v, h));
float dotNL = max(0.0, dot(n, l));
#ifdef _Anisotropy
vec3 direct;
if (abs(anisotropy) > 0.001 && dot(tangent, tangent) > 0.001) {
vec3 bitangent = normalize(cross(n, tangent));
direct = lambertDiffuseBRDF(albedo, dotNL) +
anisotropicBRDF(f0, rough, anisotropy, anisoRot,
tangent, bitangent, n, l, v, dotNL, dotNV) * spec;
} else {
direct = lambertDiffuseBRDF(albedo, dotNL) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
}
#else
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
#endif
#ifdef _ExtBRDF
float layerWeight;
direct = applyExtBRDFLayers(direct, albedo, f0, rough, dotNL, dotNV, dotNH, dotVH, n, l, v, h
#ifdef _ClearCoat
, clearcoat, clearcoatRough, coatIOR, coatTint, coatN
#endif
#ifdef _Sheen
, sheen, sheenRough, sheenTint
#endif
#ifdef _Transmission
, transmission, transRough, ior, thinWall
#endif
, layerWeight
);
#endif
direct *= lightCol;
direct *= attenuate(distance(p, lp));
direct *= attenuate(dist);
#ifdef _Spot
if (isSpot) {
@ -74,12 +121,13 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#endif
#ifdef _Clusters
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas
tileBounds = tileBoundsSpotArray[index];
direct *= shadowTest(
#ifndef _SingleAtlas
shadowMapAtlasSpot
@ -132,4 +180,41 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
return direct;
}
// Backward-compatible overload for generated shaders that don't pass extended BRDF params
#ifdef _ExtBRDF
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap
, int index, float bias, bool receiveShadow
#endif
#ifdef _Spot
, bool isSpot, float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
) {
return sampleLight(p, n, v, dotNV, lp, lightCol, albedo, rough, spec, f0
#ifdef _ShadowMap
, index, bias, receiveShadow
#endif
#ifdef _Spot
, isSpot, spotSize, spotBlend, spotDir, scale, right
#endif
#ifdef _ClearCoat
, 0.0, 0.0, 1.5, vec3(1.0), n
#endif
#ifdef _Sheen
, 0.0, 0.0, vec3(1.0)
#endif
#ifdef _Anisotropy
, 0.0, 0.0, vec3(0.0)
#endif
#ifdef _SSS
, 0.0, vec3(0.0), vec3(0.0), 0.0
#endif
#ifdef _Transmission
, 0.0, 0.0, 1.45, 1.0
#endif
);
}
#endif // _ExtBRDF
#endif

View File

@ -8,8 +8,12 @@ float hash(const vec2 p) {
}
vec2 envMapEquirect(const vec3 normal) {
const float PI = 3.1415926535;
const float PI2 = PI * 2.0;
#ifndef PI
#define PI 3.1415926535
#endif
#ifndef PI2
#define PI2 6.2831853071
#endif
float phi = acos(normal.z);
float theta = atan(-normal.y, normal.x) + PI;
return vec2(theta / PI2, phi / PI);

View File

@ -22,6 +22,14 @@ uniform vec2 smSizeUniform;
#endif
#endif
#ifdef _ShadowMapAtlas
uniform vec4 tileBoundsSunArray[maxLights * shadowmapCascades];
#if defined(_Clusters) && defined(_Spot) && defined(_ShadowMap)
uniform vec4 tileBoundsSpotArray[maxLightsCluster];
#endif
vec4 tileBounds = vec4(0.0, 0.0, 1.0, 1.0);
#endif
#ifdef _ShadowMapAtlas
// PCF that clamps samples to tile boundaries to prevent bleeding
vec3 PCFTileAware(sampler2DShadow shadowMap,
@ -291,13 +299,13 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap,
, const bool transparent
#endif
) {
const vec2 smSize = smSizeUniform; // TODO: incorrect...
const float compare = lpToDepth(lp, lightProj) - bias * 1.5;
ml = ml + n * bias * 20;
int faceIndex = 0;
const int lightIndex = index * 6;
const vec2 uv = sampleCube(ml, faceIndex);
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
const vec2 smSize = smSizeUniform; // TODO: incorrect...
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
@ -387,10 +395,6 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap,
}
#endif
#ifdef _ShadowMapAtlas
uniform vec4 tileBounds;
#endif
vec3 shadowTest(sampler2DShadow shadowMap,
#ifdef _ShadowMapTransparent
sampler2D shadowMapTransparent,
@ -405,9 +409,9 @@ vec3 shadowTest(sampler2DShadow shadowMap,
#ifdef _ShadowMapAtlas
// use tile PCF
#ifdef _SMSizeUniform
vec2 smSizeAtlas = smSizeUniform;
vec2 smSizeAtlas = smSizeUniform * (tileBounds.zw - tileBounds.xy);
#else
const vec2 smSizeAtlas = shadowmapSize;
vec2 smSizeAtlas = shadowmapSize * (tileBounds.zw - tileBounds.xy);
#endif
return PCFTileAware(shadowMap,
#ifdef _ShadowMapTransparent
@ -455,7 +459,7 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
float(d > casData[c * 4].y),
float(d > casData[c * 4].z),
float(d > casData[c * 4].w));
casi = int(min(dot(ci, comp), c));
casi = int(min(dot(ci, comp), float(c - 1)));
// Get cascade mat
casIndex = casi * 4;
return mat4(
@ -479,8 +483,12 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap,
#ifdef _SMSizeUniform
vec2 smSize = smSizeUniform;
#else
#ifdef _ShadowMapAtlas
vec2 smSize = shadowmapSize * (tileBoundsSunArray[0].zw - tileBoundsSunArray[0].xy);
#else
const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0);
#endif
#endif
const int c = shadowmapCascades;
float d = distance(eye, p);
int casi;
@ -489,16 +497,35 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap,
vec4 lPos = LWVP * vec4(p, 1.0);
lPos.xyz /= lPos.w;
#ifdef _ShadowMapAtlas
tileBounds = tileBoundsSunArray[casi];
#endif
vec3 visibility = vec3(1.0);
if (lPos.w > 0.0) visibility = PCF(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos.xy, lPos.z - shadowsBias, smSize
#ifdef _ShadowMapTransparent
, transparent
#endif
);
if (lPos.w > 0.0) {
#ifdef _ShadowMapAtlas
visibility = PCFTileAware(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos.xy, lPos.z - shadowsBias, smSize,
tileBounds.xy, tileBounds.zw
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#else
visibility = PCF(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos.xy, lPos.z - shadowsBias, smSize
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
}
// Blend cascade
// https://github.com/TheRealMJP/Shadows
@ -518,15 +545,33 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap,
lPos2.xyz /= lPos2.w;
vec3 visibility2 = vec3(1.0);
// use lPos2 coordinates for second cascade, not lPos
if (lPos2.w > 0.0) visibility2 = PCF(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos2.xy, lPos2.z - shadowsBias, smSize
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#ifdef _ShadowMapAtlas
tileBounds = tileBoundsSunArray[casi + 1];
#endif
if (lPos2.w > 0.0) {
#ifdef _ShadowMapAtlas
visibility2 = PCFTileAware(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos2.xy, lPos2.z - shadowsBias, smSize,
tileBounds.xy, tileBounds.zw
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#else
visibility2 = PCF(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos2.xy, lPos2.z - shadowsBias, smSize
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
}
float lerpAmt = smoothstep(0.0, blendThres, splitDist);
return mix(visibility2, visibility, lerpAmt);

View File

@ -1,11 +1,11 @@
/* Various sky functions
* =====================
*
* Nishita model is based on https://github.com/wwwtyro/glsl-atmosphere (Unlicense License)
* Single scattering model is based on https://github.com/wwwtyro/glsl-atmosphere (Unlicense License)
*
* Changes to the original implementation:
* - r and pSun parameters of nishita_atmosphere() are already normalized
* - Some original parameters of nishita_atmosphere() are replaced with pre-defined values
* - r and pSun parameters of single_scatter_atmosphere() are already normalized
* - Some original parameters of single_scatter_atmosphere() are replaced with pre-defined values
* - Implemented air, dust and ozone density node parameters (see Blender source)
* - Replaced the inner integral calculation with a LUT lookup
*
@ -22,43 +22,43 @@
#include "std/math.glsl"
uniform sampler2D nishitaLUT;
uniform vec2 nishitaDensity;
uniform sampler2D singleScatterLUT;
uniform vec2 skyDensity;
#ifndef PI
#define PI 3.141592
#define PI 3.1415926535
#endif
#ifndef HALF_PI
#define HALF_PI 1.570796
#endif
#define nishita_iSteps 16
#define single_scatter_iSteps 16
// These values are taken from Cycles code if they
// exist there, otherwise they are taken from the example
// in the glsl-atmosphere repo
#define nishita_sun_intensity 22.0
#define nishita_atmo_radius 6420e3
#define nishita_rayleigh_scale 8e3
#define nishita_rayleigh_coeff vec3(5.5e-6, 13.0e-6, 22.4e-6)
#define nishita_mie_scale 1.2e3
#define nishita_mie_coeff 2e-5
#define nishita_mie_dir 0.76 // Aerosols anisotropy ("direction")
#define nishita_mie_dir_sq 0.5776 // Squared aerosols anisotropy
#define single_scatter_sun_intensity 22.0
#define single_scatter_atmo_radius 6420e3
#define single_scatter_rayleigh_scale 8e3
#define single_scatter_rayleigh_coeff vec3(5.5e-6, 13.0e-6, 22.4e-6)
#define single_scatter_mie_scale 1.2e3
#define single_scatter_mie_coeff 2e-5
#define single_scatter_mie_dir 0.76 // Aerosols anisotropy ("direction")
#define single_scatter_mie_dir_sq 0.5776 // Squared aerosols anisotropy
// Values from [Hill: 60]
#define sun_limb_darkening_col vec3(0.397, 0.503, 0.652)
vec3 nishita_lookupLUT(const float height, const float sunTheta) {
vec3 single_scatter_lookupLUT(const float height, const float sunTheta) {
vec2 coords = vec2(
sqrt(height * (1 / nishita_atmo_radius)),
sqrt(height * (1 / single_scatter_atmo_radius)),
0.5 + 0.5 * sign(sunTheta - HALF_PI) * sqrt(abs(sunTheta * (1 / HALF_PI) - 1))
);
return textureLod(nishitaLUT, coords, 0.0).rgb;
return textureLod(singleScatterLUT, coords, 0.0).rgb;
}
/* See raySphereIntersection() in leenkx/Sources/renderpath/Nishita.hx */
vec2 nishita_rsi(const vec3 r0, const vec3 rd, const float sr) {
/* See raySphereIntersection() in leenkx/Sources/renderpath/Sky.hx */
vec2 single_scatter_rsi(const vec3 r0, const vec3 rd, const float sr) {
float a = dot(rd, rd);
float b = 2.0 * dot(rd, r0);
float c = dot(r0, r0) - (sr * sr);
@ -74,12 +74,12 @@ vec2 nishita_rsi(const vec3 r0, const vec3 rd, const float sr) {
* pSun: normalized sun direction
* rPlanet: planet radius
*/
vec3 nishita_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const float rPlanet) {
vec3 single_scatter_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const float rPlanet) {
// Calculate the step size of the primary ray
vec2 p = nishita_rsi(r0, r, nishita_atmo_radius);
vec2 p = single_scatter_rsi(r0, r, single_scatter_atmo_radius);
if (p.x > p.y) return vec3(0.0);
p.y = min(p.y, nishita_rsi(r0, r, rPlanet).x);
float iStepSize = (p.y - p.x) / float(nishita_iSteps);
p.y = min(p.y, single_scatter_rsi(r0, r, rPlanet).x);
float iStepSize = (p.y - p.x) / float(single_scatter_iSteps);
// Primary ray time
float iTime = 0.0;
@ -96,18 +96,18 @@ vec3 nishita_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const floa
float mu = dot(r, pSun);
float mumu = mu * mu;
float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu);
float pMie = 3.0 / (8.0 * PI) * ((1.0 - nishita_mie_dir_sq) * (mumu + 1.0)) / (pow(1.0 + nishita_mie_dir_sq - 2.0 * mu * nishita_mie_dir, 1.5) * (2.0 + nishita_mie_dir_sq));
float pMie = 3.0 / (8.0 * PI) * ((1.0 - single_scatter_mie_dir_sq) * (mumu + 1.0)) / (pow(1.0 + single_scatter_mie_dir_sq - 2.0 * mu * single_scatter_mie_dir, 1.5) * (2.0 + single_scatter_mie_dir_sq));
// Sample the primary ray
for (int i = 0; i < nishita_iSteps; i++) {
for (int i = 0; i < single_scatter_iSteps; i++) {
// Calculate the primary ray sample position and height
vec3 iPos = r0 + r * (iTime + iStepSize * 0.5);
float iHeight = length(iPos) - rPlanet;
// Calculate the optical depth of the Rayleigh and Mie scattering for this step
float odStepRlh = exp(-iHeight / nishita_rayleigh_scale) * nishitaDensity.x * iStepSize;
float odStepMie = exp(-iHeight / nishita_mie_scale) * nishitaDensity.y * iStepSize;
float odStepRlh = exp(-iHeight / single_scatter_rayleigh_scale) * skyDensity.x * iStepSize;
float odStepMie = exp(-iHeight / single_scatter_mie_scale) * skyDensity.y * iStepSize;
// Accumulate optical depth
iOdRlh += odStepRlh;
@ -116,12 +116,12 @@ vec3 nishita_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const floa
// Idea behind this: "Rotate" everything by iPos (-> iPos is the new zenith) and then all calculations for the
// inner integral only depend on the sample height (iHeight) and sunTheta (angle between sun and new zenith).
float sunTheta = safe_acos(dot(normalize(iPos), normalize(pSun)));
vec3 jAttn = nishita_lookupLUT(iHeight, sunTheta);
vec3 jAttn = single_scatter_lookupLUT(iHeight, sunTheta);
// Calculate attenuation
vec3 iAttn = exp(-(
nishita_mie_coeff * iOdMie
+ nishita_rayleigh_coeff * iOdRlh
single_scatter_mie_coeff * iOdMie
+ single_scatter_rayleigh_coeff * iOdRlh
// + 0 for ozone
));
vec3 attn = iAttn * jAttn;
@ -136,7 +136,7 @@ vec3 nishita_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const floa
iTime += iStepSize;
}
return nishita_sun_intensity * (pRlh * nishita_rayleigh_coeff * totalRlh + pMie * nishita_mie_coeff * totalMie);
return single_scatter_sun_intensity * (pRlh * single_scatter_rayleigh_coeff * totalRlh + pMie * single_scatter_mie_coeff * totalMie);
}
vec3 sun_disk(const vec3 n, const vec3 light_dir, const float disk_size, const float intensity) {
@ -149,7 +149,83 @@ vec3 sun_disk(const vec3 n, const vec3 light_dir, const float disk_size, const f
float mu = sqrt(invDist * invDist);
vec3 limb_darkening = 1.0 - (1.0 - pow(vec3(mu), sun_limb_darkening_col));
return 1 + (1.0 - step(1.0, dist)) * nishita_sun_intensity * intensity * limb_darkening;
return 1 + (1.0 - step(1.0, dist)) * single_scatter_sun_intensity * intensity * limb_darkening;
}
uniform sampler2D multiScatterLUT;
uniform vec4 multiScatterParams; // x=elevation, y=rotation, z=angular_diameter, w=intensity
uniform vec4 multiScatterSunBottom; // xyz=sun_bottom, w=earth_intersection_angle
uniform vec3 multiScatterSunTop;
// XYZ to sRGB/Rec.709 conversion (D65 white point)
vec3 xyz_to_rgb(vec3 xyz) {
return vec3(
3.2406 * xyz.x - 1.5372 * xyz.y - 0.4986 * xyz.z,
-0.9689 * xyz.x + 1.8758 * xyz.y + 0.0415 * xyz.z,
0.0557 * xyz.x - 0.2040 * xyz.y + 1.0570 * xyz.z
);
}
float sky_elevation_to_v(float elevation) {
float abs_el = abs(elevation);
float l = sign(elevation) * sqrt(abs_el / 1.5707963);
float v = (l + 1.0) * 0.5;
return clamp(v, 0.0, 1.0);
}
vec3 multi_scatter_sample_lut(vec3 dir, float sun_rotation) {
float azimuth = atan(dir.x, dir.y);
float elevation = asin(clamp(dir.z, -1.0, 1.0));
azimuth -= sun_rotation;
float u = fract(azimuth / (2.0 * PI));
float v = sky_elevation_to_v(elevation);
return textureLod(multiScatterLUT, vec2(u, v), 0.0).rgb;
}
vec3 multi_scatter_sun_disc(vec3 dir, vec3 sun_dir, float angular_diameter, float intensity) {
float half_diameter = max(angular_diameter * 0.5, 0.0005);
float dist = distance(dir, sun_dir) / half_diameter;
float edge = smoothstep(1.0, 0.95, dist);
if (edge <= 0.0) return vec3(0.0);
float horizon = multiScatterSunBottom.w;
float dir_elev = asin(clamp(dir.z, -1.0, 1.0));
float horizon_fade = smoothstep(horizon - half_diameter * 0.1, horizon + half_diameter * 0.1, dir_elev);
edge *= horizon_fade;
if (edge <= 0.0) return vec3(0.0);
float invDist = 1.0 - dist;
float mu = sqrt(invDist * invDist);
vec3 limb_darkening = 1.0 - (1.0 - pow(vec3(mu), sun_limb_darkening_col));
float sun_elev = multiScatterParams.x;
float t = clamp((dir_elev - (sun_elev - half_diameter)) / (2.0 * half_diameter), 0.0, 1.0);
vec3 sun_color = mix(multiScatterSunBottom.rgb, multiScatterSunTop, t) * intensity * limb_darkening;
return xyz_to_rgb(sun_color) * edge;
}
vec3 multi_scatter_atmosphere(vec3 dir) {
float sun_elevation = multiScatterParams.x;
float sun_rotation = multiScatterParams.y;
float angular_diameter = multiScatterParams.z;
float sun_intensity = multiScatterParams.w;
vec3 xyz = multi_scatter_sample_lut(dir, sun_rotation);
vec3 radiance = xyz_to_rgb(xyz);
if (sun_intensity > 0.0) {
vec3 computed_sun_dir = vec3(
sin(sun_rotation) * cos(sun_elevation),
cos(sun_rotation) * cos(sun_elevation),
sin(sun_elevation)
);
radiance += multi_scatter_sun_disc(dir, computed_sun_dir, angular_diameter, sun_intensity);
}
return radiance;
}
#endif

View File

@ -1,15 +1,25 @@
// Separable SSS Transmittance Function, ref to sss_pass
vec3 SSSSTransmittance(mat4 LWVP, vec3 p, vec3 n, vec3 l, float lightFar, sampler2DShadow shadowMap) {
const float translucency = 1.0;
vec3 SSSSTransmittance(mat4 LWVP, vec3 p, vec3 n, vec3 l, float lightFar, sampler2DShadow shadowMap, vec3 sssColor, float sssRadius
#ifdef _ShadowMapAtlas
, vec4 tileBounds
#endif
) {
const float translucency = 0.85;
vec4 shrinkedPos = vec4(p - 0.005 * n, 1.0);
vec4 shadowPos = LWVP * shrinkedPos;
float scale = 8.25 * (1.0 - translucency) / (sssWidth / 10.0);
float d1 = texture(shadowMap, vec3(shadowPos.xy / shadowPos.w, shadowPos.z)).r; // 'd1' has a range of 0..1
float d2 = shadowPos.z; // 'd2' has a range of 0..'lightFarPlane'
d1 *= lightFar; // So we scale 'd1' accordingly:
float d = scale * abs(d1 - d2);
vec2 shadowUV = shadowPos.xy / shadowPos.w;
#ifdef _ShadowMapAtlas
shadowUV = clamp(shadowUV, tileBounds.xy, tileBounds.zw);
#endif
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
float d1 = texture(shadowMap, vec3(shadowUV, shadowPos.z)).r;
float d2 = shadowPos.z;
d1 *= lightFar;
d2 *= lightFar;
float d = scale * abs(d1 - d2) * 1000.0;
if (d > 10.0) return vec3(0.0);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
@ -17,10 +27,70 @@ vec3 SSSSTransmittance(mat4 LWVP, vec3 p, vec3 n, vec3 l, float lightFar, sample
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
return profile * clamp(0.3 + dot(l, -n), 0.0, 1.0);
profile *= mix(vec3(1.0), sssColor, 0.8);
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
}
vec3 SSSSTransmittanceCube(float translucency, vec4 shadowPos, vec3 n, vec3 l, float lightFar) {
// TODO
return vec3(0.0);
#ifdef _ShadowMapAtlas
vec3 SSSSTransmittanceCubeAtlas(sampler2DShadow shadowMap, vec3 lightPos, vec3 p, vec3 n, vec3 l, float lightFar, vec2 lightProj, int index, vec3 sssColor, float sssRadius) {
const float translucency = 0.85;
vec3 shrinkedPos = p - 0.005 * n;
vec3 ld = normalize(shrinkedPos - lightPos);
#ifdef _InvY
ld.y = -ld.y;
#endif
float d2 = lpToDepth(ld, lightProj);
int faceIndex = 0;
int lightIndex = index * 6;
vec2 uv = sampleCube(ld, faceIndex);
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex];
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y;
#endif
float d1 = texture(shadowMap, vec3(uvtiled, d2)).r;
d1 *= lightFar;
d2 *= lightFar;
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
// d1/d2 are in meters, sssRadius is in mm, exponential constants are in mm^2
float d = scale * abs(d1 - d2) * 1000.0; // Convert distance to mm
if (d > 10.0) return vec3(0.0);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
profile *= mix(vec3(1.0), sssColor, 0.8);
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
}
#endif
vec3 SSSSTransmittanceCube(samplerCubeShadow shadowMapCube, vec3 lightPos, vec3 p, vec3 n, vec3 l, float lightFar, vec2 lightProj, vec3 sssColor, float sssRadius) {
const float translucency = 0.85;
vec3 shrinkedPos = p - 0.005 * n;
vec3 ld = normalize(shrinkedPos - lightPos);
#ifdef _InvY
ld.y = -ld.y;
#endif
float d2 = lpToDepth(ld, lightProj);
float d1 = texture(shadowMapCube, vec4(ld, d2)).r;
d1 *= lightFar;
d2 *= lightFar;
float scale = 2.5 * (1.0 - translucency) / max(sssRadius, 0.001);
// d1/d2 are in meters, sssRadius is in mm, exponential constants are in mm^2
float d = scale * abs(d1 - d2) * 1000.0; // Convert distance to mm
if (d > 10.0) return vec3(0.0);
float dd = -d * d;
vec3 profile = vec3(0.233, 0.455, 0.649) * exp(dd / 0.0064) +
vec3(0.1, 0.336, 0.344) * exp(dd / 0.0484) +
vec3(0.118, 0.198, 0.0) * exp(dd / 0.187) +
vec3(0.113, 0.007, 0.007) * exp(dd / 0.567) +
vec3(0.358, 0.004, 0.0) * exp(dd / 1.99) +
vec3(0.078, 0.0, 0.0) * exp(dd / 7.41);
profile *= mix(vec3(1.0), sssColor, 0.8);
return profile * clamp(0.5 + dot(l, -n), 0.0, 1.0);
}

View File

@ -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));
}

View File

@ -38,7 +38,6 @@ uniform layout(r8) image3D voxelsOut;
#endif
uniform int clipmapLevel;
uniform float voxelBlend;
uniform float clipmaps[voxelgiClipmapCount * 10];
@ -47,7 +46,7 @@ void main() {
ivec3 src = ivec3(gl_GlobalInvocationID.xyz);
src.y += clipmapLevel * res;
for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++)
for (int i = 0; i < 6 + diffuseConeCount; i++)
{
vec4 col = vec4(0.0);

View File

@ -165,7 +165,7 @@ void main() {
#endif
#endif
envl.rgb *= envmapStrength * occspec.x;
envl.rgb *= envmapStrength * voxelgiEnv * occspec.x;
vec3 occ = envl * (1.0 - traceAO(P, n, voxels, clipmaps));

View File

@ -53,13 +53,6 @@ uniform float shirr[7 * 4];
#ifdef _Brdf
uniform sampler2D senvmapBrdf;
#endif
#ifdef _Rad
uniform sampler2D senvmapRadiance;
uniform int envmapNumMipmaps;
#endif
#ifdef _EnvCol
uniform vec3 backgroundCol;
#endif
void main() {
const vec2 pixel = gl_GlobalInvocationID.xy;
@ -140,17 +133,8 @@ void main() {
vec3 envl = vec3(0.0);
#endif
#ifdef _Rad
vec3 reflectionWorld = reflect(-v, n);
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
#endif
#ifdef _EnvLDR
envl.rgb = pow(envl.rgb, vec3(2.2));
#ifdef _Rad
prefilteredColor = pow(prefilteredColor, vec3(2.2));
#endif
#endif
envl.rgb *= albedo;
@ -159,15 +143,7 @@ void main() {
envl.rgb *= 1.0 - F; //LV: We should take refracted light into account
#endif
#ifdef _Rad // Indirect specular
envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT
#else
#ifdef _EnvCol
envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0?
#endif
#endif
envl.rgb *= envmapStrength * occspec.x;
envl.rgb *= envmapStrength * voxelgiEnv * occspec.x;
vec4 trace = traceDiffuse(P, n, voxels, clipmaps);
vec3 color = trace.rgb * albedo * (1.0 - F);

View File

@ -48,13 +48,15 @@ void main() {
const vec2 pixel = gl_GlobalInvocationID.xy;
vec2 uv = (pixel + 0.5) / postprocess_resolution;
#ifdef _InvY
uv.y = 1.0 - uv.y
uv.y = 1.0 - uv.y;
#endif
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
if (depth == 0) return;
vec2 ior_opac = textureLod(gbuffer_refraction, uv, 0.0).xy;
float ior = unpackIOR(ior_opac.x);
float opacity = ior_opac.y;
float x = uv.x * 2 - 1;
float y = uv.y * 2 - 1;
@ -72,8 +74,8 @@ void main() {
n = normalize(n);
vec3 color = vec3(0.0);
if(ior_opac.y < 1.0)
color = traceRefraction(P, n, voxels, voxelsSDF, normalize(eye - P), ior_opac.x, g0.b, clipmaps, pixel).rgb;
if(opacity < 1.0)
color = traceRefraction(P, n, voxels, voxelsSDF, normalize(eye - P), ior, g0.b, clipmaps, pixel).rgb;
imageStore(voxels_refraction, ivec2(pixel), vec4(color, 1.0));
}

View File

@ -66,9 +66,13 @@ void main() {
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
n = normalize(n);
float roughness = g0.b;
vec3 v = normalize(eye - P);
vec2 velocity = -textureLod(sveloc, uv, 0.0).rg;
vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb;
vec3 color = traceSpecular(P, n, voxels, voxelsSDF, v, roughness * roughness, clipmaps, pixel, velocity).rgb;
imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0));
}

View File

@ -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++)
for (int i = 0; i < 6 + diffuseConeCount; 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;
@ -138,8 +136,9 @@ void main() {
radiance = basecol;
vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps);
vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a);
radiance.rgb *= light.rgb + indirect.rgb;
radiance.rgb *= light.rgb * INV_PI + indirect.rgb;
radiance.rgb += emission.rgb;
}
#else
opac = float(imageLoad(voxels, src)) / 255;
@ -196,7 +195,7 @@ void main() {
}
else {
// precompute cone sampling:
vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6];
vec3 coneDirection = diffuseConeDirections[i - 6];
vec3 aniso_direction = -coneDirection;
uvec3 face_offsets = uvec3(
aniso_direction.x > 0 ? 0 : 1,

View File

@ -88,58 +88,103 @@ vec4 rayCast(vec3 dir) {
}
#endif //SSR
vec3 sampleWaterNormals(vec2 hitXY, float speed, out vec2 tcnor0, out vec2 tcnor1) {
tcnor0 = hitXY / 3.0;
vec3 n0 = textureLod(sdetail, tcnor0 + vec2(speed / 60.0, speed / 120.0), 0.0).rgb;
tcnor1 = hitXY / 6.0 + n0.xy / 20.0;
vec3 n1 = textureLod(sbase, tcnor1 + vec2(speed / 40.0, speed / 80.0), 0.0).rgb;
return normalize(n0 + n1 - 1.0);
}
void main() {
float gdepth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
if (gdepth == 1.0) {
fragColor = vec4(0.0);
return;
}
// Eye below water
if (eye.z < waterLevel) {
fragColor = vec4(0.0);
return;
}
// Displace surface
vec3 vray = normalize(viewRay);
vec3 p = getPos(eye, eyeLook, vray, gdepth, cameraProj);
float speed = time * 2.0 * waterSpeed;
p.z += sin(p.x * 10.0 / waterDisplace + speed) * cos(p.y * 10.0 / waterDisplace + speed) / 50.0 * waterDisplace;
bool isSky = (gdepth == 1.0);
// Ray-plane intersection with water surface (z = waterLevel)
float denom = dot(vray, vec3(0.0, 0.0, 1.0));
float tWater = (waterLevel - eye.z) / denom;
bool hasWaterHit = (abs(denom) > 0.0001) && (tWater > 0.0);
if (eye.z < waterLevel) {
vec2 tc = texCoord;
float fogFactor;
if (hasWaterHit && denom > 0.0) {
// Looking up at water surface - apply normal distortion
vec3 hit = eye + tWater * vray;
vec2 tc0, tc1;
vec3 n2 = sampleWaterNormals(hit.xy * waterFreq, speed, tc0, tc1);
tc = texCoord + (n2.xy * n2.z) / 30.0 * waterRefract;
fogFactor = clamp(tWater * waterDensity, 0.0, 0.95);
} else {
// Looking forward/down - distort via water surface above fragment
vec3 p = getPos(eye, eyeLook, vray, gdepth, cameraProj);
vec2 wxy = isSky ? (eye.xy + vray.xy * 50.0) : p.xy;
vec2 tc0, tc1;
vec3 n2 = sampleWaterNormals(wxy * waterFreq, speed, tc0, tc1);
tc = texCoord + (n2.xy * n2.z) / 30.0 * waterRefract;
float waterDist = isSky ? 50.0 : length(p - eye);
fogFactor = clamp(waterDist * waterDensity, 0.0, 0.95);
}
vec3 refracted = textureLod(tex, tc, 0.0).rgb;
fragColor.rgb = mix(refracted, waterColor, fogFactor);
fragColor.a = 1.0;
return;
}
// Above water
if (p.z > waterLevel) {
if (!hasWaterHit || denom >= 0.0) {
fragColor = vec4(0.0);
return;
}
if (isSky) tWater = min(tWater, 100.0); // Clamp to prevent aliasing at horizon
vec3 p = isSky ? (eye + tWater * vray) : getPos(eye, eyeLook, vray, gdepth, cameraProj);
float horizonFactor = clamp(1.0 - tWater / 60.0, 0.0, 1.0);
if (!isSky && p.z > waterLevel) {
fragColor = vec4(0.0);
return;
}
// Displace surface
p.z += (sin(p.x * 10.0 / waterDisplace + speed) * cos(p.y * 10.0 / waterDisplace + speed)
+ sin(p.x * 20.0 / waterDisplace + speed * 1.3) * cos(p.y * 20.0 / waterDisplace + speed * 1.3) * 0.5)
/ 50.0 * waterDisplace;
// Hit plane to determine uvs
vec3 v = normalize(eye - p.xyz);
float t = -(dot(eye, vec3(0.0, 0.0, 1.0)) - waterLevel) / dot(v, vec3(0.0, 0.0, 1.0));
vec3 v = normalize(eye - p);
float t = (waterLevel - eye.z) / dot(v, vec3(0.0, 0.0, 1.0));
vec3 hit = eye + t * v;
hit.xy *= waterFreq;
hit.z += waterLevel;
// Sample normal maps
vec2 tcnor0 = hit.xy / 3.0;
vec3 n0 = textureLod(sdetail, tcnor0 + vec2(speed / 60.0, speed / 120.0), 0.0).rgb;
vec2 tcnor0, tcnor1;
vec3 n2 = sampleWaterNormals(hit.xy * waterFreq, speed, tcnor0, tcnor1);
vec2 tcnor1 = hit.xy / 6.0 + n0.xy / 20.0;
vec3 n1 = textureLod(sbase, tcnor1 + vec2(speed / 40.0, speed / 80.0), 0.0).rgb;
vec3 n2 = normalize(((n1 + n0) / 2.0) * 2.0 - 1.0);
float ddepth = textureLod(gbufferD, texCoord + (n2.xy * n2.z) / 40.0, 0.0).r * 2.0 - 1.0;
vec3 p2 = getPos(eye, eyeLook, vray, ddepth, cameraProj);
vec2 tc = p2.z > waterLevel ? texCoord : texCoord + (n2.xy * n2.z) / 30.0 * waterRefract;
// Refraction
vec2 tc;
if (isSky) {
tc = texCoord + (n2.xy * n2.z) / 30.0 * waterRefract;
} else {
float ddepth = textureLod(gbufferD, texCoord + (n2.xy * n2.z) / 40.0, 0.0).r * 2.0 - 1.0;
vec3 p2 = getPos(eye, eyeLook, vray, ddepth, cameraProj);
tc = p2.z > waterLevel ? texCoord : texCoord + (n2.xy * n2.z) / 30.0 * waterRefract;
}
// Light
float fresnel = 1.0 - max(dot(n2, v), 0.0);
fresnel = pow(fresnel, 30.0) * 0.45;
fresnel = 0.02 + 0.98 * pow(fresnel, 5.0);
vec3 r = reflect(-v, n2);
#ifdef _Rad
vec3 reflectedEnv = textureLod(senvmapRadiance, envMapEquirect(r), 0).rgb;
vec3 reflectedEnv = textureLod(senvmapRadiance, envMapEquirect(r), 0).rgb;
#else
const vec3 reflectedEnv = vec3(0.5);
#endif
vec3 refracted = textureLod(tex, tc, 0.0).rgb;
#ifdef _SSR
float roughness = 0.1;//unpackFloat(g0.b).y;
//if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
@ -147,8 +192,8 @@ void main() {
float spec = 0.9;//fract(textureLod(gbuffer1, texCoord, 0.0).a);
//if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
vec3 viewNormal = n2;
vec3 viewPos = getPosView(viewRay, gdepth, cameraProj);
vec3 viewNormal = V3 * n2;
vec3 viewPos = isSky ? vec3(0.0) : getPosView(viewRay, gdepth, cameraProj);
vec3 reflected = reflect(normalize(viewPos), viewNormal);
hitCoord = viewPos;
@ -158,7 +203,6 @@ void main() {
vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0;
#endif
// * max(ssrMinRayStep, -viewPos.z)
vec4 coords = rayCast(dir);
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
@ -177,20 +221,32 @@ void main() {
#else
fragColor.rgb = mix(refracted, reflectedEnv, waterReflect * fresnel);
#endif
fragColor.rgb *= waterColor;
fragColor.rgb += clamp(pow(max(dot(r, ld), 0.0), 200.0) * (200.0 + 8.0) / (PI * 8.0), 0.0, 2.0);
fragColor.rgb *= 1.0 - (clamp(-(p.z - waterLevel) * waterDensity, 0.0, 0.9));
fragColor.a = clamp(abs(p.z - waterLevel) * 5.0, 0.0, 1.0);
// Water color tint - blend rather than multiply to preserve brightness
float colorMix = isSky ? 0.7 : 0.5;
fragColor.rgb = mix(fragColor.rgb, fragColor.rgb * waterColor, colorMix * horizonFactor);
// Blinn-Phong specular using half-vector, faded at horizon
vec3 h = normalize(v + ld);
float specAmount = pow(max(dot(n2, h), 0.0), 200.0) * (200.0 + 8.0) / (PI * 8.0);
fragColor.rgb += specAmount * (isSky ? 0.3 : 1.0) * horizonFactor;
// Depth fog - blend toward waterColor with depth, faded at horizon
float depthFog = clamp(-(p.z - waterLevel) * waterDensity, 0.0, 0.9);
fragColor.rgb = mix(fragColor.rgb, waterColor, depthFog * horizonFactor);
// Alpha fades smoothly at horizon instead of hard cut
fragColor.a = isSky ? horizonFactor : clamp(abs(p.z - waterLevel) * 5.0, 0.0, 1.0);
// Foam
float fd = abs(p.z - waterLevel);
// Foam - based on actual geometry depth below water surface
float fd = isSky ? 1.0 : abs(p.z - waterLevel);
if (fd < 0.1) {
// Based on foam by Owen Deery
// http://fire-face.com/personal/water
vec3 foamMask0 = textureLod(sfoam, tcnor0 * 10, 0.0).rgb;
vec3 foamMask1 = textureLod(sfoam, tcnor1 * 11, 0.0).rgb;
vec3 foam = vec3(1.0) - foamMask0.rrr - foamMask1.bbb;
float fac = 1.0 - (fd * (1.0 / 0.1));
fragColor.rgb = mix(fragColor.rgb, clamp(foam, 0.0, 1.0), clamp(fac, 0.0, 1.0));
// Distance-based LOD blurs foam at range to reduce noise
float foamLod = clamp(tWater / 15.0, 0.0, 5.0);
vec2 foamUV0 = tcnor0 * 3.0 + vec2(speed / 30.0, speed / 50.0);
vec2 foamUV1 = tcnor1 * 4.0 + vec2(-speed / 35.0, speed / 45.0);
vec3 foamMask0 = textureLod(sfoam, foamUV0, foamLod).rgb;
vec3 foamMask1 = textureLod(sfoam, foamUV1, foamLod).rgb;
float foamStrength = clamp(1.0 - foamMask0.r * 0.5 - foamMask1.b * 0.5, 0.0, 1.0);
float fac = (1.0 - (fd * (1.0 / 0.1))) * horizonFactor;
fragColor.rgb = mix(fragColor.rgb, mix(fragColor.rgb, waterColor + 0.2, foamStrength), clamp(fac, 0.0, 1.0) * 0.5);
}
}

View File

@ -304,10 +304,13 @@ class RenderPath {
currentD = 1;
currentFace = -1;
meshesSorted = false;
sun = null;
for (l in Scene.active.lights) {
if (l.visible) l.buildMatrix(Scene.active.camera);
if (l.data.raw.type == "sun") sun = l;
if (l.data.raw.type == "sun") {
if (sun == null || (!sun.data.raw.cast_shadow && l.data.raw.cast_shadow)) sun = l;
}
else point = l;
}
light = Scene.active.lights[0];
@ -500,7 +503,7 @@ class RenderPath {
}
public function drawMeshes(context: String) {
var isShadows = context == "shadowmap";
var isShadows = context == "shadowmap" || context == "shadowmap_transparent";
if (isShadows) {
// Disabled shadow casting for this light
if (light == null || !light.data.raw.cast_shadow || !light.visible || light.data.raw.strength == 0) return;
@ -672,7 +675,7 @@ class RenderPath {
}
#if (rp_voxels != "Off")
public function getComputeShader(handle: String): kha.compute.Shader {
public function getComputeShader(handle: String): kha.graphics4.ComputeShader {
return Reflect.field(kha.Shaders, handle + "_comp");
}
#end

View File

@ -71,6 +71,13 @@ class Scene {
public var embedded: Map<String, kha.Image>;
#if (rp_renderer == "Deferred")
public static inline var MAX_MATERIALS = 16;
public static inline var FLOATS_PER_MATERIAL_PARAM = 32; // 8 vec4s per material
public var materialParamsBuffer: kha.arrays.Float32Array;
public var materialParamsDirty: Bool = true;
#end
public var ready: Bool; // Async in progress
public var traitInits: Array<Void->Void> = [];
@ -107,6 +114,9 @@ class Scene {
armatures = [];
#end
embedded = new Map();
#if (rp_renderer == "Deferred")
materialParamsBuffer = new kha.arrays.Float32Array(MAX_MATERIALS * FLOATS_PER_MATERIAL_PARAM);
#end
root = new Object();
root.name = "Root";
traitInits = [];
@ -204,6 +214,89 @@ class Scene {
root.remove();
}
#if (rp_renderer == "Deferred")
public function markMaterialParamsDirty() {
materialParamsDirty = true;
}
public function updateMaterialParams() {
if (!materialParamsDirty) return;
materialParamsDirty = false;
var buf = materialParamsBuffer;
for (m in meshes) {
if (m.materials == null) continue;
for (mat in m.materials) {
if (mat == null) continue;
if (mat.contexts == null) continue;
var slot = -1;
var bc = null;
for (ctx in mat.contexts) {
if (ctx == null || ctx.raw == null) continue;
if (ctx.raw.name == "mesh" && ctx.raw.bind_constants != null) {
bc = ctx.raw.bind_constants;
for (c in bc) {
if (c != null && c.name == "materialID" && c.intValue != null) {
slot = c.intValue;
}
}
break;
}
}
if (slot < 0 || slot >= MAX_MATERIALS) continue;
var base = slot * FLOATS_PER_MATERIAL_PARAM;
if (base + FLOATS_PER_MATERIAL_PARAM - 1 >= buf.length) continue;
if (bc == null) continue;
for (i in 0...FLOATS_PER_MATERIAL_PARAM) buf[base + i] = 0.0;
buf[base + 6] = 1.5; // coatIOR
buf[base + 12] = 1.45; // ior
buf[base + 13] = 1.0; // thinWall
for (c in bc) {
if (c == null || c.name == null || c.floatValue == null) continue;
switch (c.name) {
// matp0: vec4(anisotropy, anisoRot, sheen, sheenRough)
case "anisotropy": buf[base + 0] = c.floatValue;
case "anisoRot": buf[base + 1] = c.floatValue;
case "sheen": buf[base + 2] = c.floatValue;
case "sheenRough": buf[base + 3] = c.floatValue;
// matp1: vec4(clearcoat, clearcoatRough, coatIOR, coatTintR)
case "clearcoat": buf[base + 4] = c.floatValue;
case "clearcoatRough": buf[base + 5] = c.floatValue;
case "coatIOR": buf[base + 6] = c.floatValue;
case "coatTintR": buf[base + 7] = c.floatValue;
// matp2: vec4(coatTintG, coatTintB, transmission, transRough)
case "coatTintG": buf[base + 8] = c.floatValue;
case "coatTintB": buf[base + 9] = c.floatValue;
case "transmission": buf[base + 10] = c.floatValue;
case "transmissionRough": buf[base + 11] = c.floatValue;
// matp3: vec4(ior, thinWall, subsurface, subsurfaceAnisotropy)
case "ior": buf[base + 12] = c.floatValue;
case "thinWall": buf[base + 13] = c.floatValue;
case "subsurface": buf[base + 14] = c.floatValue;
case "subsurfaceAnisotropy": buf[base + 15] = c.floatValue;
// matp4: vec4(subsurfaceRadiusR, subsurfaceRadiusG, subsurfaceRadiusB, subsurfaceColorR)
case "subsurfaceRadiusR": buf[base + 16] = c.floatValue;
case "subsurfaceRadiusG": buf[base + 17] = c.floatValue;
case "subsurfaceRadiusB": buf[base + 18] = c.floatValue;
case "subsurfaceColorR": buf[base + 19] = c.floatValue;
// matp5: vec4(subsurfaceColorG, subsurfaceColorB, sheenTintR, sheenTintG)
case "subsurfaceColorG": buf[base + 20] = c.floatValue;
case "subsurfaceColorB": buf[base + 21] = c.floatValue;
case "sheenTintR": buf[base + 22] = c.floatValue;
case "sheenTintG": buf[base + 23] = c.floatValue;
// matp6: vec4(sheenTintB, specularTintR, specularTintG, specularTintB)
case "sheenTintB": buf[base + 24] = c.floatValue;
case "specularTintR": buf[base + 25] = c.floatValue;
case "specularTintG": buf[base + 26] = c.floatValue;
case "specularTintB": buf[base + 27] = c.floatValue;
// matp7: vec4(subsurfaceScale, 0, 0, 0)
case "subsurfaceScale": buf[base + 28] = c.floatValue;
}
}
}
}
}
#end
static var framePassed = true;
public static function setActive(sceneName: String, done: Object->Void = null) {
if (!framePassed) return;
@ -351,6 +444,9 @@ class Scene {
public function addMeshObject(data: MeshData, materials: Vector<MaterialData>, parent: Object = null): MeshObject {
var object = new MeshObject(data, materials);
parent != null ? object.setParent(parent) : object.setParent(root);
#if (rp_renderer == "Deferred")
markMaterialParamsDirty();
#end
return object;
}

View File

@ -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) {

View File

@ -348,7 +348,13 @@ typedef TWorldData = {
@:optional public var turbidity: Null<FastFloat>;
@:optional public var ground_albedo: Null<FastFloat>;
@:optional public var envmap: String;
@:optional public var nishita_density: Float32Array; // Rayleigh, Mie, ozone
@:optional public var sky_density: Float32Array; // Air, dust/aerosol, ozone density
@:optional public var sky_sun_elevation: Null<FastFloat>;
@:optional public var sky_sun_rotation: Null<FastFloat>;
@:optional public var sky_sun_size: Null<FastFloat>;
@:optional public var sky_sun_intensity: Null<FastFloat>;
@:optional public var sky_altitude: Null<FastFloat>;
@:optional public var sky_sun_disc: Null<Int>; // 0 or 1
}
#if js

View File

@ -245,7 +245,12 @@ class LightObject extends Object {
// Snap to texel coords - fix translation swim
var smsize = data.raw.shadowmap_size;
#if lnx_csm // Cascades
smsize = Std.int(smsize / 4);
#if lnx_shadowmap_atlas
var ts = cascade < tileScale.length ? tileScale[cascade] : 1.0;
smsize = Std.int(Math.max(ts * data.raw.shadowmap_size, 1.0));
#else
smsize = Std.int(smsize / cascadeCount);
#end
#end
var worldPerTexelX = (maxx - minx) / smsize;
var worldPerTexelY = (maxy - miny) / smsize;
@ -685,22 +690,6 @@ class LightObject extends Object {
return LWVPMatrixArray;
}
public static inline function getMaxLights(): Int {
#if (rp_max_lights == 8)
return 8;
#elseif (rp_max_lights == 16)
return 16;
#elseif (rp_max_lights == 24)
return 24;
#elseif (rp_max_lights == 32)
return 32;
#elseif (rp_max_lights == 64)
return 64;
#else
return 4;
#end
}
public static inline function getMaxLightsCluster(): Int {
#if (rp_max_lights_cluster == 8)
return 8;
@ -718,6 +707,90 @@ class LightObject extends Object {
}
#end // lnx_clusters
public static inline function getMaxLights(): Int {
#if (rp_max_lights == 8)
return 8;
#elseif (rp_max_lights == 16)
return 16;
#elseif (rp_max_lights == 24)
return 24;
#elseif (rp_max_lights == 32)
return 32;
#elseif (rp_max_lights == 64)
return 64;
#else
return 4;
#end
}
#if (rp_shadowmap && lnx_shadowmap_atlas)
public static var sunTileBoundsArray: Float32Array = null;
public static var tileBoundsDirty: Bool = true;
public static function updateSunTileBoundsArray(): Float32Array {
if (!tileBoundsDirty && sunTileBoundsArray != null) return sunTileBoundsArray;
tileBoundsDirty = false;
var maxLights = getMaxLights();
var numTiles = maxLights * cascadeCount;
if (sunTileBoundsArray == null) {
sunTileBoundsArray = new Float32Array(numTiles * 4);
}
for (k in 0...sunTileBoundsArray.length) sunTileBoundsArray[k] = 0;
var i = 0;
for (light in Scene.active.lights) {
if (i >= maxLights) break;
if (!light.visible || light.data.raw.type != "sun") continue;
if (!light.data.raw.cast_shadow || light.data.raw.strength == 0.0) continue;
for (c in 0...cascadeCount) {
var idx = (i * cascadeCount + c) * 4;
sunTileBoundsArray[idx ] = light.tileOffsetX[c];
sunTileBoundsArray[idx + 2] = light.tileOffsetX[c] + light.tileScale[c];
#if (!kha_opengl)
// flip bounds to match
sunTileBoundsArray[idx + 1] = 1.0 - (light.tileOffsetY[c] + light.tileScale[c]);
sunTileBoundsArray[idx + 3] = 1.0 - light.tileOffsetY[c];
#else
sunTileBoundsArray[idx + 1] = light.tileOffsetY[c];
sunTileBoundsArray[idx + 3] = light.tileOffsetY[c] + light.tileScale[c];
#end
}
i++;
}
return sunTileBoundsArray;
}
#end
#if (rp_shadowmap && lnx_shadowmap_atlas)
public static var spotTileBoundsArray: Float32Array = null;
public static function updateSpotTileBoundsArray(): Float32Array {
var maxLights = getMaxLights();
if (spotTileBoundsArray == null) {
spotTileBoundsArray = new Float32Array(maxLights * 4);
}
for (k in 0...spotTileBoundsArray.length) spotTileBoundsArray[k] = 0;
var i = 0;
for (light in Scene.active.lights) {
if (i >= maxLights) break;
if (!light.visible || light.data.raw.type != "spot") continue;
if (!light.data.raw.cast_shadow || light.data.raw.strength == 0.0) continue;
var idx = i * 4;
spotTileBoundsArray[idx ] = light.tileOffsetX[0];
spotTileBoundsArray[idx + 2] = light.tileOffsetX[0] + light.tileScale[0];
#if (!kha_opengl)
// flip bounds
spotTileBoundsArray[idx + 1] = 1.0 - (light.tileOffsetY[0] + light.tileScale[0]);
spotTileBoundsArray[idx + 3] = 1.0 - light.tileOffsetY[0];
#else
spotTileBoundsArray[idx + 1] = light.tileOffsetY[0];
spotTileBoundsArray[idx + 3] = light.tileOffsetY[0] + light.tileScale[0];
#end
i++;
}
return spotTileBoundsArray;
}
#end
public inline function right(): Vec4 {
return new Vec4(V._00, V._10, V._20);
}

View File

@ -89,6 +89,9 @@ class MeshObject extends Object {
#end
if (tilesheet != null) tilesheet.remove();
if (Scene.active != null) Scene.active.meshes.remove(this);
#if (rp_renderer == "Deferred")
if (Scene.active != null) Scene.active.markMaterialParamsDirty();
#end
data.refcount--;
super.remove();
}
@ -318,9 +321,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]);

View File

@ -394,7 +394,7 @@ class ParticleSystemCPU {
if (physics.hasScaleRamp && physics.rampPositions.length > 1) {
var normalizedAge: FastFloat = physics.age / physics.lifetime;
var scaleMultiplier: FastFloat = interpolateRampValue(normalizedAge, physics.rampPositions, physics.rampColors);
var finalScale: FastFloat = scale * (particleScale * (1 - physics.scaleRampSizeFactor) + scaleMultiplier * physics.scaleRampSizeFactor);
var finalScale: FastFloat = 1 + (scaleMultiplier - 1) * physics.scaleRampSizeFactor;
particle.transform.scale.setFrom(physics.baseScale.clone().mult(finalScale));
}

View File

@ -827,9 +827,20 @@ class Uniforms {
}
}
case "_shadowMapSize": {
if (light != null && light.data.raw.cast_shadow) {
var shadowLight = light;
if (shadowLight == null || !shadowLight.data.raw.cast_shadow) {
shadowLight = RenderPath.active.sun;
}
if (shadowLight != null && shadowLight.data.raw.cast_shadow) {
v = helpVec;
v.x = v.y = light.data.raw.shadowmap_size;
v.x = v.y = shadowLight.data.raw.shadowmap_size;
#if lnx_csm
#if (!lnx_shadowmap_atlas)
if (shadowLight.data.raw.type == "sun") {
v.x = shadowLight.data.raw.shadowmap_size * LightObject.cascadeCount;
}
#end
#end
}
}
default:
@ -887,6 +898,11 @@ class Uniforms {
case "_envmapIrradiance": {
fa = Scene.active.world == null ? WorldData.getEmptyIrradiance() : Scene.active.world.probe.irradiance;
}
#if (rp_renderer == "Deferred")
case "_materialParams": {
fa = Scene.active.materialParamsBuffer;
}
#end
#if lnx_clusters
case "_lightsArray": {
fa = LightObject.lightsArray;
@ -903,15 +919,18 @@ class Uniforms {
#end
#end // lnx_clusters
#if lnx_csm
case "_cascadeData": {
for (l in Scene.active.lights) {
if (l.data.raw.type == "sun") {
fa = l.getCascadeData();
break;
}
}
case "_cascadeData": {
var sun = RenderPath.active.sun;
if (sun != null && sun.data.raw.type == "sun") {
fa = sun.getCascadeData();
}
#end
}
#end
#if lnx_shadowmap_atlas
case "_tileBoundsSunArray": {
fa = LightObject.updateSunTileBoundsArray();
}
#end
}
if (fa != null) {
@ -1064,32 +1083,30 @@ class Uniforms {
}
}
case "_biasLightWorldViewProjectionMatrixSun": {
for (l in iron.Scene.active.lights) {
if (l.data.raw.type == "sun") {
// object is null for DrawQuad
object == null ? helpMat.setIdentity() : helpMat.setFrom(object.transform.worldUnpack);
helpMat.multmat(l.VP);
helpMat.multmat(biasMat);
#if lnx_shadowmap_atlas
// tile matrix
helpMat2.setIdentity();
// scale [0-1] coords to [0-tilescale]
helpMat2._00 = l.tileScale[0];
helpMat2._11 = l.tileScale[0];
// offset coordinate start from [0, 0] to [tile-start-x, tile-start-y]
helpMat2._30 = l.tileOffsetX[0];
helpMat2._31 = l.tileOffsetY[0];
helpMat.multmat(helpMat2);
#if (!kha_opengl)
helpMat2.setIdentity();
helpMat2._11 = -1.0;
helpMat2._31 = 1.0;
helpMat.multmat(helpMat2);
#end
#end
m = helpMat;
break;
}
var sun = RenderPath.active.sun;
if (sun != null && sun.data.raw.type == "sun") {
// object is null for DrawQuad
object == null ? helpMat.setIdentity() : helpMat.setFrom(object.transform.worldUnpack);
helpMat.multmat(sun.VP);
helpMat.multmat(biasMat);
#if lnx_shadowmap_atlas
// tile matrix
helpMat2.setIdentity();
// scale [0-1] coords to [0-tilescale]
helpMat2._00 = sun.tileScale[0];
helpMat2._11 = sun.tileScale[0];
// offset coordinate start from [0, 0] to [tile-start-x, tile-start-y]
helpMat2._30 = sun.tileOffsetX[0];
helpMat2._31 = sun.tileOffsetY[0];
helpMat.multmat(helpMat2);
#if (!kha_opengl)
helpMat2.setIdentity();
helpMat2._11 = -1.0;
helpMat2._31 = 1.0;
helpMat.multmat(helpMat2);
#end
#end
m = helpMat;
}
}
#if rp_probes
@ -1373,7 +1390,7 @@ class Uniforms {
if (fa == null) return;
g.setFloats(location, fa);
}
else if (c.type == "int") {
else if (c.type == "int" || c.type == "uint") {
var i: Null<Int> = null;
switch (c.link) {
case "_uid": {

View File

@ -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

View File

@ -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
}
}

View File

@ -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";
}
}

View File

@ -1,27 +0,0 @@
package leenkx.logicnode;
import iron.math.Vec4;
class GetHosekWilkiePropertiesNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var world = iron.Scene.active.world.raw;
return switch (from) {
case 0:
world.turbidity;
case 1:
world.ground_albedo;
case 2:
new Vec4(world.sun_direction[0], world.sun_direction[1], world.sun_direction[2]);
default:
null;
}
return null;
}
}

View File

@ -1,29 +0,0 @@
package leenkx.logicnode;
import iron.math.Vec4;
class GetNishitaPropertiesNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var world = iron.Scene.active.world.raw;
return switch (from) {
case 0:
world.nishita_density[0];
case 1:
world.nishita_density[1];
case 2:
world.nishita_density[2];
case 3:
new Vec4(world.sun_direction[0], world.sun_direction[1], world.sun_direction[2]);
default:
null;
}
return null;
}
}

View File

@ -0,0 +1,15 @@
package leenkx.logicnode;
import iron.math.Vec4;
class GetWorldColorNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var col = iron.Scene.active.world.raw.background_color;
return new Vec4(((col >> 16) & 0xff) / 255, ((col >> 8) & 0xff) / 255, (col & 0xff) / 255, 1.0);
}
}

View File

@ -0,0 +1,50 @@
package leenkx.logicnode;
import iron.math.Vec4;
class GetWorldSkyNode extends LogicNode {
public var property0:String;
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var world = iron.Scene.active.world.raw;
if (property0 == 'hosek') {
return switch (from) {
case 0: world.turbidity != null ? world.turbidity : 1.0;
case 1: world.ground_albedo != null ? world.ground_albedo : 0.0;
case 2: world.sun_direction != null ? new Vec4(world.sun_direction[0], world.sun_direction[1], world.sun_direction[2]) : new Vec4(0, 0, 1);
default: null;
}
}
else if (property0 == 'single') {
return switch (from) {
case 0: world.sky_density != null ? world.sky_density[0] : 1.0;
case 1: world.sky_density != null ? world.sky_density[1] : 1.0;
case 2: world.sky_density != null ? world.sky_density[2] : 1.0;
case 3: world.sky_altitude != null ? world.sky_altitude : 0.0;
case 4: world.sun_direction != null ? new Vec4(world.sun_direction[0], world.sun_direction[1], world.sun_direction[2]) : new Vec4(0, 0, 1);
default: null;
}
}
else { // multi
return switch (from) {
case 0: world.sky_density != null ? world.sky_density[0] : 1.0;
case 1: world.sky_density != null ? world.sky_density[1] : 1.0;
case 2: world.sky_density != null ? world.sky_density[2] : 1.0;
case 3: world.sky_sun_elevation != null ? world.sky_sun_elevation : 0.0;
case 4: world.sky_sun_rotation != null ? world.sky_sun_rotation : 0.0;
case 5: world.sky_sun_size != null ? world.sky_sun_size : 0.545;
case 6: world.sky_sun_intensity != null ? world.sky_sun_intensity : 1.0;
case 7: world.sky_altitude != null ? world.sky_altitude : 0.0;
case 8: world.sky_sun_disc != null ? world.sky_sun_disc : 1;
case 9: world.sun_direction != null ? new Vec4(world.sun_direction[0], world.sun_direction[1], world.sun_direction[2]) : new Vec4(0, 0, 1);
default: null;
}
}
}
}

View File

@ -0,0 +1,17 @@
package leenkx.logicnode;
class GetWorldTextureNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var world = iron.Scene.active.world;
return switch (from) {
case 0: world.probe != null ? world.probe.raw.strength : 1.0;
case 1: world.raw.envmap != null ? world.raw.envmap : '';
default: null;
}
}
}

View 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);
}
}

View 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);
}
}

View 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);
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View 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
}
}

View File

@ -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);
}
}

View 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);
}
}

View 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;
}
}

View File

@ -20,6 +20,7 @@ class LeenkxSendMessageNode extends LogicNode {
}
override function run(from:Int) {
#if js
var connection = inputs[1].get();
if (connection == null) return;
var api: String = inputs[2].get();
@ -348,6 +349,7 @@ class LeenkxSendMessageNode extends LogicNode {
return;
}
}
#end
}
}

View File

@ -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");

Some files were not shown because too many files have changed in this diff Show More