Compare commits
4 Commits
main
...
brdf_rewri
| Author | SHA1 | Date | |
|---|---|---|---|
| e569352f0b | |||
| 5b5de92890 | |||
| 0cdb90bdb8 | |||
| ddc3a071f4 |
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,2 +0,0 @@
|
|||||||
*.hdr binary
|
|
||||||
blender/lnx/props.py ident
|
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,5 +0,0 @@
|
|||||||
__pycache__/
|
|
||||||
*.pyc
|
|
||||||
*.DS_Store
|
|
||||||
**/workspace.xml
|
|
||||||
**/vcs.xml
|
|
||||||
@ -227,7 +227,7 @@ class SystemImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline var maxGamepads: Int = 4;
|
static inline var maxGamepads: Int = 4;
|
||||||
public static var frame: Framebuffer;
|
static var frame: Framebuffer;
|
||||||
static var keyboard: Keyboard = null;
|
static var keyboard: Keyboard = null;
|
||||||
static var mouse: kha.input.Mouse;
|
static var mouse: kha.input.Mouse;
|
||||||
static var surface: Surface;
|
static var surface: Surface;
|
||||||
@ -388,8 +388,7 @@ class SystemImpl {
|
|||||||
{
|
{
|
||||||
alpha: false,
|
alpha: false,
|
||||||
antialias: options.framebuffer.samplesPerPixel > 1,
|
antialias: options.framebuffer.samplesPerPixel > 1,
|
||||||
stencil: true,
|
stencil: true
|
||||||
xrCompatible: true
|
|
||||||
}); // preserveDrawingBuffer: true } ); Warning: preserveDrawingBuffer can cause huge performance issues on mobile browsers
|
}); // preserveDrawingBuffer: true } ); Warning: preserveDrawingBuffer can cause huge performance issues on mobile browsers
|
||||||
SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
|
SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
|
||||||
|
|
||||||
@ -418,8 +417,7 @@ class SystemImpl {
|
|||||||
{
|
{
|
||||||
alpha: false,
|
alpha: false,
|
||||||
antialias: options.framebuffer.samplesPerPixel > 1,
|
antialias: options.framebuffer.samplesPerPixel > 1,
|
||||||
stencil: true,
|
stencil: true
|
||||||
xrCompatible: true
|
|
||||||
}); // preserveDrawingBuffer: true } ); WARNING: preserveDrawingBuffer causes huge performance issues (on mobile browser)!
|
}); // preserveDrawingBuffer: true } ); WARNING: preserveDrawingBuffer causes huge performance issues (on mobile browser)!
|
||||||
SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
|
SystemImpl.gl.pixelStorei(GL.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
|
||||||
SystemImpl.gl.getExtension("OES_texture_float");
|
SystemImpl.gl.getExtension("OES_texture_float");
|
||||||
@ -549,12 +547,6 @@ class SystemImpl {
|
|||||||
];
|
];
|
||||||
|
|
||||||
function animate(timestamp) {
|
function animate(timestamp) {
|
||||||
if (untyped Browser.window._khaSkipWindowRender == true) {
|
|
||||||
if (requestAnimationFrame != null)
|
|
||||||
requestAnimationFrame(animate);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requestAnimationFrame == null)
|
if (requestAnimationFrame == null)
|
||||||
Browser.window.setTimeout(animate, 1000.0 / 60.0);
|
Browser.window.setTimeout(animate, 1000.0 / 60.0);
|
||||||
else
|
else
|
||||||
|
|||||||
@ -47,7 +47,6 @@ class Graphics implements kha.graphics4.Graphics {
|
|||||||
|
|
||||||
static var current: Graphics = null;
|
static var current: Graphics = null;
|
||||||
static var useVertexAttributes: Int = 0;
|
static var useVertexAttributes: Int = 0;
|
||||||
public static var vrFramebufferBound: Bool = false;
|
|
||||||
|
|
||||||
public function new(renderTarget: Canvas = null) {
|
public function new(renderTarget: Canvas = null) {
|
||||||
this.renderTarget = renderTarget;
|
this.renderTarget = renderTarget;
|
||||||
@ -90,11 +89,9 @@ class Graphics implements kha.graphics4.Graphics {
|
|||||||
SystemImpl.gl.enable(GL.BLEND);
|
SystemImpl.gl.enable(GL.BLEND);
|
||||||
SystemImpl.gl.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA);
|
SystemImpl.gl.blendFunc(GL.SRC_ALPHA, GL.ONE_MINUS_SRC_ALPHA);
|
||||||
if (renderTarget == null) {
|
if (renderTarget == null) {
|
||||||
if (!vrFramebufferBound) {
|
|
||||||
SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null);
|
SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, null);
|
||||||
SystemImpl.gl.viewport(0, 0, System.windowWidth(), System.windowHeight());
|
SystemImpl.gl.viewport(0, 0, System.windowWidth(), System.windowHeight());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, renderTargetFrameBuffer);
|
SystemImpl.gl.bindFramebuffer(GL.FRAMEBUFFER, renderTargetFrameBuffer);
|
||||||
// if (isCubeMap) SystemImpl.gl.framebufferTexture(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_CUBE_MAP, renderTargetTexture, 0); // Layered
|
// if (isCubeMap) SystemImpl.gl.framebufferTexture(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_CUBE_MAP, renderTargetTexture, 0); // Layered
|
||||||
|
|||||||
@ -13,29 +13,10 @@ import kha.SystemImpl;
|
|||||||
|
|
||||||
class VrInterface extends kha.vr.VrInterface {
|
class VrInterface extends kha.vr.VrInterface {
|
||||||
var vrEnabled: Bool = false;
|
var vrEnabled: Bool = false;
|
||||||
var isWebXR: Bool = false;
|
|
||||||
|
|
||||||
var vrDisplay: Dynamic;
|
var vrDisplay: Dynamic;
|
||||||
var frameData: Dynamic;
|
var frameData: Dynamic;
|
||||||
|
|
||||||
var xrSession: Dynamic;
|
|
||||||
var xrRefSpace: Dynamic;
|
|
||||||
public var xrGLLayer: Dynamic;
|
|
||||||
public var currentFrame: Dynamic;
|
|
||||||
public var currentViews: Dynamic;
|
|
||||||
public var currentViewerPose: Dynamic;
|
|
||||||
public var currentInputSources: Dynamic;
|
|
||||||
var xrAnimationFrameHandle: Int = -1;
|
|
||||||
|
|
||||||
public var _glContext: Dynamic;
|
|
||||||
public var _leftViewport: Dynamic;
|
|
||||||
public var _rightViewport: Dynamic;
|
|
||||||
public var _cachedViewsLength: Int = 0;
|
|
||||||
|
|
||||||
var savedCanvasWidth: Int = 0;
|
|
||||||
var savedCanvasHeight: Int = 0;
|
|
||||||
var browserRAFId: Int = -1;
|
|
||||||
|
|
||||||
var leftProjectionMatrix: FastMatrix4 = FastMatrix4.identity();
|
var leftProjectionMatrix: FastMatrix4 = FastMatrix4.identity();
|
||||||
var rightProjectionMatrix: FastMatrix4 = FastMatrix4.identity();
|
var rightProjectionMatrix: FastMatrix4 = FastMatrix4.identity();
|
||||||
var leftViewMatrix: FastMatrix4 = FastMatrix4.identity();
|
var leftViewMatrix: FastMatrix4 = FastMatrix4.identity();
|
||||||
@ -49,29 +30,15 @@ class VrInterface extends kha.vr.VrInterface {
|
|||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
#if kha_webvr
|
#if kha_webvr
|
||||||
var webXREnabled: Bool = Syntax.code("navigator.xr");
|
|
||||||
if (webXREnabled) {
|
|
||||||
isWebXR = true;
|
|
||||||
vrEnabled = true;
|
|
||||||
trace("WebXR API detected");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var displayEnabled: Bool = Syntax.code("navigator.getVRDisplays");
|
var displayEnabled: Bool = Syntax.code("navigator.getVRDisplays");
|
||||||
if (displayEnabled) {
|
|
||||||
isWebXR = false;
|
|
||||||
vrEnabled = true;
|
|
||||||
getVRDisplays();
|
|
||||||
trace("WebVR 1.1 API detected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
var displayEnabled = false;
|
var displayEnabled = false;
|
||||||
#end
|
#end
|
||||||
//if (displayEnabled) {
|
if (displayEnabled) {
|
||||||
// vrEnabled = true;
|
vrEnabled = true;
|
||||||
// getVRDisplays();
|
getVRDisplays();
|
||||||
// trace("Display enabled.");
|
trace("Display enabled.");
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVRDisplays() {
|
function getVRDisplays() {
|
||||||
@ -97,10 +64,6 @@ class VrInterface extends kha.vr.VrInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override function onVRRequestPresent() {
|
public override function onVRRequestPresent() {
|
||||||
if (isWebXR) {
|
|
||||||
requestWebXRSession();
|
|
||||||
} else {
|
|
||||||
// WebVR 1.1
|
|
||||||
try {
|
try {
|
||||||
vrDisplay.requestPresent([{source: SystemImpl.khanvas}]).then(function() {
|
vrDisplay.requestPresent([{source: SystemImpl.khanvas}]).then(function() {
|
||||||
onResize();
|
onResize();
|
||||||
@ -108,466 +71,22 @@ class VrInterface extends kha.vr.VrInterface {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (err:Dynamic) {
|
catch (err:Dynamic) {
|
||||||
trace("Failed to requestPresent WebVR: " + err);
|
trace("Failed to requestPresent.");
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function requestWebXRSession() {
|
|
||||||
var vrScaleFactor = 1.0;
|
|
||||||
#if lnx_vr
|
|
||||||
vrScaleFactor = leenkx.renderpath.Inc.getSuperSampling();
|
|
||||||
trace("[VR] Using renderpath superSample as framebufferScaleFactor: " + vrScaleFactor);
|
|
||||||
#end
|
|
||||||
|
|
||||||
try {
|
|
||||||
Syntax.code("
|
|
||||||
|
|
||||||
|
|
||||||
let gl = null;
|
|
||||||
let canvas = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (typeof kha_SystemImpl !== 'undefined') {
|
|
||||||
gl = kha_SystemImpl.gl;
|
|
||||||
canvas = kha_SystemImpl.khanvas;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
trace('kha_SystemImpl access failed: ' + e.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!canvas) {
|
|
||||||
canvas = document.querySelector('canvas');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canvas && !gl) {
|
|
||||||
const contextAttributes = { xrCompatible: true, antialias: true, alpha: false };
|
|
||||||
gl = canvas.getContext('webgl2', contextAttributes) ||
|
|
||||||
canvas.getContext('webgl', contextAttributes) ||
|
|
||||||
canvas.getContext('experimental-webgl', contextAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!canvas) {
|
|
||||||
canvas = document.getElementById('khanvas');
|
|
||||||
if (canvas && !gl) {
|
|
||||||
gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const self = this;
|
|
||||||
const glContext = gl;
|
|
||||||
|
|
||||||
self._glContext = glContext;
|
|
||||||
");
|
|
||||||
|
|
||||||
Syntax.code("
|
|
||||||
self._vrRenderCallback = function() {
|
|
||||||
self.vrRenderCallback();
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkAndRequestSession = async () => {
|
|
||||||
try {
|
|
||||||
const supported = await navigator.xr.isSessionSupported('immersive-vr');
|
|
||||||
if (!supported) {
|
|
||||||
trace('immersive-vr session not supported');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
trace('WARN: isSessionSupported failed: ' + e.message);
|
|
||||||
// Continue anyway as some browsers do not support the check itself
|
|
||||||
}
|
|
||||||
|
|
||||||
return await navigator.xr.requestSession('immersive-vr', {
|
|
||||||
optionalFeatures: ['local-floor', 'hand-tracking', 'bounded-floor']
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
checkAndRequestSession().then(async (session) => {
|
|
||||||
self.xrSession = session;
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
window._khaSkipWindowRender = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const contextAttributes = glContext.getContextAttributes();
|
|
||||||
if (!contextAttributes || !contextAttributes.xrCompatible) {
|
|
||||||
await glContext.makeXRCompatible();
|
|
||||||
}
|
|
||||||
self.xrGLLayer = new XRWebGLLayer(session, glContext, {
|
|
||||||
depth: true, // Essential for depth testing
|
|
||||||
stencil: false, // Not needed, wastes memory
|
|
||||||
alpha: false, // Not needed in VR wastes
|
|
||||||
antialias: true, // Smooth rendering
|
|
||||||
framebufferScaleFactor: {0} // VR resolution quality from renderpath
|
|
||||||
});
|
|
||||||
|
|
||||||
if (self.xrGLLayer.framebufferWidth === 0 || self.xrGLLayer.framebufferHeight === 0) {
|
|
||||||
trace('XRWebGLLayer framebuffer has invalid dimensions');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
session.updateRenderState({
|
|
||||||
baseLayer: self.xrGLLayer
|
|
||||||
});
|
|
||||||
const handlers = {};
|
|
||||||
|
|
||||||
handlers.end = () => {
|
|
||||||
self.onSessionEnd();
|
|
||||||
};
|
|
||||||
session.addEventListener('end', handlers.end);
|
|
||||||
|
|
||||||
handlers.select = (event) => {
|
|
||||||
if (self.onSelect) self.onSelect(event);
|
|
||||||
};
|
|
||||||
session.addEventListener('select', handlers.select);
|
|
||||||
|
|
||||||
handlers.selectstart = (event) => {
|
|
||||||
if (self.onSelectStart) self.onSelectStart(event);
|
|
||||||
};
|
|
||||||
session.addEventListener('selectstart', handlers.selectstart);
|
|
||||||
|
|
||||||
handlers.selectend = (event) => {
|
|
||||||
if (self.onSelectEnd) self.onSelectEnd(event);
|
|
||||||
};
|
|
||||||
session.addEventListener('selectend', handlers.selectend);
|
|
||||||
|
|
||||||
handlers.squeeze = (event) => {
|
|
||||||
if (self.onSqueeze) self.onSqueeze(event);
|
|
||||||
};
|
|
||||||
session.addEventListener('squeeze', handlers.squeeze);
|
|
||||||
|
|
||||||
handlers.squeezestart = (event) => {
|
|
||||||
if (self.onSqueezeStart) self.onSqueezeStart(event);
|
|
||||||
};
|
|
||||||
session.addEventListener('squeezestart', handlers.squeezestart);
|
|
||||||
|
|
||||||
handlers.squeezeend = (event) => {
|
|
||||||
if (self.onSqueezeEnd) self.onSqueezeEnd(event);
|
|
||||||
};
|
|
||||||
session.addEventListener('squeezeend', handlers.squeezeend);
|
|
||||||
|
|
||||||
session.addEventListener('inputsourceschange', handlers.inputsourceschange);
|
|
||||||
|
|
||||||
handlers.visibilitychange = (event) => {
|
|
||||||
const state = event.session.visibilityState;
|
|
||||||
|
|
||||||
};
|
|
||||||
session.addEventListener('visibilitychange', handlers.visibilitychange);
|
|
||||||
|
|
||||||
self._eventHandlers = handlers;
|
|
||||||
|
|
||||||
const requestRefSpace = async () => {
|
|
||||||
const spaces = ['local-floor', 'local'];
|
|
||||||
for (const space of spaces) {
|
|
||||||
try {
|
|
||||||
const refSpace = await session.requestReferenceSpace(space);
|
|
||||||
return refSpace;
|
|
||||||
} catch (e) {
|
|
||||||
trace(space + ' not supported');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trace('No reference space supported');
|
|
||||||
};
|
|
||||||
|
|
||||||
requestRefSpace().then((refSpace) => {
|
|
||||||
self.xrRefSpace = refSpace;
|
|
||||||
|
|
||||||
if (canvas && canvas.width) {
|
|
||||||
self.savedCanvasWidth = canvas.width;
|
|
||||||
self.savedCanvasHeight = canvas.height;
|
|
||||||
} else {
|
|
||||||
const canvasFallback = document.querySelector('canvas');
|
|
||||||
if (canvasFallback) {
|
|
||||||
self.savedCanvasWidth = canvasFallback.width;
|
|
||||||
self.savedCanvasHeight = canvasFallback.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onFrame = (time, frame) => {
|
|
||||||
try {
|
|
||||||
if (self.xrSession) {
|
|
||||||
self.xrAnimationFrameHandle = self.xrSession.requestAnimationFrame(onFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self._lastFrameTime) self._lastFrameTime = time;
|
|
||||||
const deltaTime = time - self._lastFrameTime;
|
|
||||||
self._lastFrameTime = time;
|
|
||||||
|
|
||||||
if (!window._xrFrameCount) window._xrFrameCount = 0;
|
|
||||||
window._xrFrameCount++;
|
|
||||||
|
|
||||||
if (glContext && self.xrSession && self.xrSession.renderState && self.xrSession.renderState.baseLayer) {
|
|
||||||
const layer = self.xrSession.renderState.baseLayer;
|
|
||||||
if (layer.framebuffer) {
|
|
||||||
const pose = frame.getViewerPose(self.xrRefSpace);
|
|
||||||
if (pose && pose.views && pose.views.length > 0) {
|
|
||||||
glContext.bindFramebuffer(glContext.FRAMEBUFFER, layer.framebuffer);
|
|
||||||
|
|
||||||
let bgR = 0, bgG = 0, bgB = 0;
|
|
||||||
if (typeof iron !== 'undefined' && iron.Scene && iron.Scene.active && iron.Scene.active.world && iron.Scene.active.world.raw) {
|
|
||||||
const bgColor = iron.Scene.active.world.raw.background_color;
|
|
||||||
if (bgColor !== undefined) {
|
|
||||||
bgR = ((bgColor >> 16) & 255) / 255;
|
|
||||||
bgG = ((bgColor >> 8) & 255) / 255;
|
|
||||||
bgB = (bgColor & 255) / 255;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const view of pose.views) {
|
|
||||||
const vp = layer.getViewport(view);
|
|
||||||
glContext.viewport(vp.x, vp.y, vp.width, vp.height);
|
|
||||||
glContext.scissor(vp.x, vp.y, vp.width, vp.height);
|
|
||||||
glContext.enable(glContext.SCISSOR_TEST);
|
|
||||||
|
|
||||||
glContext.clearColor(bgR, bgG, bgB, 1.0);
|
|
||||||
glContext.clear(glContext.COLOR_BUFFER_BIT | glContext.DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
}
|
|
||||||
glContext.disable(glContext.SCISSOR_TEST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self.xrSession) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pose = frame.getViewerPose(self.xrRefSpace);
|
|
||||||
if (!pose) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pose.emulatedPosition && !self._emulatedPosLogged) {
|
|
||||||
self._emulatedPosLogged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const views = pose.views;
|
|
||||||
|
|
||||||
if (!self.xrSession.renderState || !self.xrSession.renderState.baseLayer) {
|
|
||||||
if (!self._noRenderStateLogged) {
|
|
||||||
self._noRenderStateLogged = true;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const glLayer = self.xrSession.renderState.baseLayer;
|
|
||||||
|
|
||||||
if (!views || views.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.xrSession.visibilityState === 'hidden') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.currentFrame = frame;
|
|
||||||
self.currentViews = views;
|
|
||||||
self.currentViewerPose = pose;
|
|
||||||
if (self.xrSession && self.xrSession.inputSources) {
|
|
||||||
self.currentInputSources = self.xrSession.inputSources;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glContext.isContextLost()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!glContext || !glLayer || !glLayer.framebuffer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (glContext.bindVertexArray) {
|
|
||||||
glContext.bindVertexArray(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (glContext.getError() !== glContext.NO_ERROR) {
|
|
||||||
// Drain error queue
|
|
||||||
}
|
|
||||||
|
|
||||||
glContext.bindFramebuffer(glContext.FRAMEBUFFER, glLayer.framebuffer);
|
|
||||||
|
|
||||||
|
|
||||||
const bindError = glContext.getError();
|
|
||||||
if (bindError !== glContext.NO_ERROR && !self._bindErrorLogged) {
|
|
||||||
self._bindErrorLogged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fbStatus = glContext.checkFramebufferStatus(glContext.FRAMEBUFFER);
|
|
||||||
if (fbStatus !== glContext.FRAMEBUFFER_COMPLETE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glContext.enable(glContext.DEPTH_TEST);
|
|
||||||
glContext.depthFunc(glContext.LEQUAL);
|
|
||||||
glContext.depthMask(true);
|
|
||||||
glContext.colorMask(true, true, true, true);
|
|
||||||
glContext.disable(glContext.BLEND);
|
|
||||||
glContext.enable(glContext.CULL_FACE);
|
|
||||||
glContext.cullFace(glContext.BACK);
|
|
||||||
glContext.frontFace(glContext.CCW);
|
|
||||||
glContext.disable(glContext.STENCIL_TEST);
|
|
||||||
glContext.disable(glContext.POLYGON_OFFSET_FILL);
|
|
||||||
|
|
||||||
|
|
||||||
if (!self._fbLogged && p) {
|
|
||||||
const depthTest = glContext.isEnabled(glContext.DEPTH_TEST);
|
|
||||||
const cullFace = glContext.isEnabled(glContext.CULL_FACE);
|
|
||||||
const blend = glContext.isEnabled(glContext.BLEND);
|
|
||||||
self._fbLogged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (views.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (views.length >= 1) {
|
|
||||||
try {
|
|
||||||
self._leftViewport = glLayer.getViewport(views[0]);
|
|
||||||
self._rightViewport = views.length >= 2 ? glLayer.getViewport(views[1]) : null;
|
|
||||||
self._cachedViewsLength = views.length;
|
|
||||||
|
|
||||||
if (!self._leftViewport) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (views.length >= 1) {
|
|
||||||
self.leftProjectionMatrix = self.createMatrixFromArray(views[0].projectionMatrix);
|
|
||||||
self.leftViewMatrix = self.createMatrixFromArray(views[0].transform.inverse.matrix);
|
|
||||||
}
|
|
||||||
if (views.length >= 2) {
|
|
||||||
self.rightProjectionMatrix = self.createMatrixFromArray(views[1].projectionMatrix);
|
|
||||||
self.rightViewMatrix = self.createMatrixFromArray(views[1].transform.inverse.matrix);
|
|
||||||
} else if (views.length === 1) {
|
|
||||||
self.rightProjectionMatrix = self.leftProjectionMatrix;
|
|
||||||
self.rightViewMatrix = self.leftViewMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self._vrRenderCallback) {
|
|
||||||
self._vrRenderCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error('XR Frame Error:', err);
|
|
||||||
} finally {
|
|
||||||
self.currentFrame = null;
|
|
||||||
self.currentViews = null;
|
|
||||||
self.currentInputSources = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.xrAnimationFrameHandle = session.requestAnimationFrame(onFrame);
|
|
||||||
}).catch((err) => {
|
|
||||||
trace('REF SPACE FAILED: ' + err.message );
|
|
||||||
});
|
|
||||||
}).catch((err) => {
|
|
||||||
trace('SESSION FAILED: ' + err);
|
|
||||||
});
|
|
||||||
", vrScaleFactor);
|
|
||||||
}
|
|
||||||
catch (err:Dynamic) {
|
|
||||||
trace("Failed to requestSession (WebXR).");
|
|
||||||
trace(err);
|
trace(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSessionEnd() {
|
|
||||||
var canvas = SystemImpl.khanvas;
|
|
||||||
if (canvas == null) {
|
|
||||||
canvas = Syntax.code("document.querySelector('canvas')");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canvas != null && savedCanvasWidth > 0 && savedCanvasHeight > 0) {
|
|
||||||
canvas.width = savedCanvasWidth;
|
|
||||||
canvas.height = savedCanvasHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xrSession != null) {
|
|
||||||
Syntax.code("
|
|
||||||
if (this.xrAnimationFrameHandle !== -1 && this.xrSession) {
|
|
||||||
this.xrSession.cancelAnimationFrame(this.xrAnimationFrameHandle);
|
|
||||||
this.xrAnimationFrameHandle = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._eventHandlers && this.xrSession) {
|
|
||||||
const handlers = this._eventHandlers;
|
|
||||||
const events = ['end', 'select', 'selectstart', 'selectend', 'squeeze', 'squeezestart', 'squeezeend', 'inputsourceschange', 'visibilitychange'];
|
|
||||||
for (const event of events) {
|
|
||||||
if (handlers[event]) {
|
|
||||||
this.xrSession.removeEventListener(event, handlers[event]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._eventHandlers = null;
|
|
||||||
}
|
|
||||||
");
|
|
||||||
}
|
|
||||||
|
|
||||||
Syntax.code("
|
|
||||||
const gl = this._glContext;
|
|
||||||
if (gl) {
|
|
||||||
gl.bindFramebuffer(gl.FRAMEBUFFER, null); // Restore default framebuffer
|
|
||||||
gl.disable(gl.SCISSOR_TEST);
|
|
||||||
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
window._khaSkipWindowRender = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.xrSession = null;
|
|
||||||
this.xrRefSpace = null;
|
|
||||||
this.xrGLLayer = null;
|
|
||||||
this.currentFrame = null;
|
|
||||||
this.currentViews = null;
|
|
||||||
this.currentInputSources = null;
|
|
||||||
this._lastFrameTime = null;
|
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
delete window._xrFrameCount;
|
|
||||||
delete window._ironRenderCount;
|
|
||||||
delete window._slowFrameCount;
|
|
||||||
}
|
|
||||||
");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override function onVRExitPresent() {
|
public override function onVRExitPresent() {
|
||||||
if (isWebXR) {
|
|
||||||
try {
|
|
||||||
if (xrSession != null) {
|
|
||||||
Syntax.code("
|
|
||||||
if (this.xrSession) {
|
|
||||||
this.xrSession.end().then(() => {
|
|
||||||
trace('Session ended');
|
|
||||||
}).catch((err) => {
|
|
||||||
trace('Session.end() failed:', err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
");
|
|
||||||
xrSession = null;
|
|
||||||
xrRefSpace = null;
|
|
||||||
xrGLLayer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (err:Dynamic) {
|
|
||||||
trace("Failed to exitPresent in WebXR");
|
|
||||||
trace(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// WebVR 1.1
|
|
||||||
try {
|
try {
|
||||||
vrDisplay.exitPresent([{source: SystemImpl.khanvas}]).then(function() {
|
vrDisplay.exitPresent([{source: SystemImpl.khanvas}]).then(function() {
|
||||||
onResize();
|
onResize();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (err:Dynamic) {
|
catch (err:Dynamic) {
|
||||||
trace("Failed to exitPresent");
|
trace("Failed to exitPresent.");
|
||||||
trace(err);
|
trace(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public override function onResetPose() {
|
public override function onResetPose() {
|
||||||
try {
|
try {
|
||||||
@ -597,25 +116,13 @@ class VrInterface extends kha.vr.VrInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onResize() {
|
function onResize() {
|
||||||
if (isWebXR) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// WebVR 1.1
|
|
||||||
if (vrDisplay != null && vrDisplay.isPresenting) {
|
if (vrDisplay != null && vrDisplay.isPresenting) {
|
||||||
var canvas = SystemImpl.khanvas;
|
SystemImpl.khanvas.width = vrWidth;
|
||||||
if (canvas != null) {
|
SystemImpl.khanvas.height = vrHeight;
|
||||||
canvas.width = vrWidth;
|
|
||||||
canvas.height = vrHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var canvas = SystemImpl.khanvas;
|
SystemImpl.khanvas.width = width;
|
||||||
if (canvas != null) {
|
SystemImpl.khanvas.height = height;
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,11 +174,9 @@ class VrInterface extends kha.vr.VrInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override function IsPresenting(): Bool {
|
public override function IsPresenting(): Bool {
|
||||||
var presenting = false;
|
if (vrDisplay != null)
|
||||||
if (vrDisplay != null){
|
return vrDisplay.isPresenting;
|
||||||
presenting = vrDisplay.isPresenting;
|
return false;
|
||||||
}
|
|
||||||
return presenting;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function IsVrEnabled(): Bool {
|
public override function IsVrEnabled(): Bool {
|
||||||
@ -702,10 +207,6 @@ class VrInterface extends kha.vr.VrInterface {
|
|||||||
|
|
||||||
function createMatrixFromArray(array: Float32Array): FastMatrix4 {
|
function createMatrixFromArray(array: Float32Array): FastMatrix4 {
|
||||||
var matrix: FastMatrix4 = FastMatrix4.identity();
|
var matrix: FastMatrix4 = FastMatrix4.identity();
|
||||||
if (array == null || array.length < 16) {
|
|
||||||
trace("Warning: Invalid matrix array, using identity");
|
|
||||||
return matrix;
|
|
||||||
}
|
|
||||||
matrix._00 = array[0];
|
matrix._00 = array[0];
|
||||||
matrix._01 = array[1];
|
matrix._01 = array[1];
|
||||||
matrix._02 = array[2];
|
matrix._02 = array[2];
|
||||||
@ -745,63 +246,4 @@ class VrInterface extends kha.vr.VrInterface {
|
|||||||
}
|
}
|
||||||
return quaternion;
|
return quaternion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function vrRenderCallback(): Void {
|
|
||||||
var g4 = kha.SystemImpl.frame != null ? kha.SystemImpl.frame.g4 : null;
|
|
||||||
|
|
||||||
|
|
||||||
if (g4 != null && iron.Scene.active != null && iron.RenderPath.active != null) {
|
|
||||||
|
|
||||||
if (untyped window._vrUpdateStarted == null) {
|
|
||||||
untyped window._vrUpdateStarted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
iron.system.Time.update();
|
|
||||||
|
|
||||||
iron.Scene.active.updateFrame();
|
|
||||||
|
|
||||||
|
|
||||||
js.Syntax.code("
|
|
||||||
const App = iron.App;
|
|
||||||
if (App) {
|
|
||||||
const frame = window._vrCallbackCount;
|
|
||||||
const inits = App.traitInits;
|
|
||||||
if (inits && inits.length > 0) {
|
|
||||||
for (let i = 0; i < inits.length; i++) {
|
|
||||||
inits[i]();
|
|
||||||
}
|
|
||||||
inits.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fixedUpdates = App.traitFixedUpdates;
|
|
||||||
if (fixedUpdates) {
|
|
||||||
for (let i = 0; i < fixedUpdates.length; i++) {
|
|
||||||
fixedUpdates[i]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const updates = App.traitUpdates;
|
|
||||||
if (updates) {
|
|
||||||
for (let i = 0; i < updates.length; i++) {
|
|
||||||
updates[i]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const lateUpdates = App.traitLateUpdates;
|
|
||||||
if (lateUpdates) {
|
|
||||||
for (let i = 0; i < lateUpdates.length; i++) {
|
|
||||||
lateUpdates[i]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
");
|
|
||||||
iron.Scene.active.renderFrame(g4);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (untyped window._vrSkipLogged == null) {
|
|
||||||
untyped window._vrSkipLogged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,7 +80,6 @@ extern class Krom {
|
|||||||
static function unloadImage(image: kha.Image): Void;
|
static function unloadImage(image: kha.Image): Void;
|
||||||
static function loadSound(file: String): Dynamic;
|
static function loadSound(file: String): Dynamic;
|
||||||
static function writeAudioBuffer(buffer: js.lib.ArrayBuffer, samples: Int): Void;
|
static function writeAudioBuffer(buffer: js.lib.ArrayBuffer, samples: Int): Void;
|
||||||
static function getSamplesPerSecond(): Int;
|
|
||||||
static function loadBlob(file: String): js.lib.ArrayBuffer;
|
static function loadBlob(file: String): js.lib.ArrayBuffer;
|
||||||
|
|
||||||
static function init(title: String, width: Int, height: Int, samplesPerPixel: Int, vSync: Bool, windowMode: Int, windowFeatures: Int, kromApi: Int): Void;
|
static function init(title: String, width: Int, height: Int, samplesPerPixel: Int, vSync: Bool, windowMode: Int, windowFeatures: Int, kromApi: Int): Void;
|
||||||
@ -116,7 +115,6 @@ extern class Krom {
|
|||||||
static function screenDpi(): Int;
|
static function screenDpi(): Int;
|
||||||
static function systemId(): String;
|
static function systemId(): String;
|
||||||
static function requestShutdown(): Void;
|
static function requestShutdown(): Void;
|
||||||
static function displayFrequency(): Int;
|
|
||||||
static function displayCount(): Int;
|
static function displayCount(): Int;
|
||||||
static function displayWidth(index: Int): Int;
|
static function displayWidth(index: Int): Int;
|
||||||
static function displayHeight(index: Int): Int;
|
static function displayHeight(index: Int): Int;
|
||||||
@ -157,5 +155,4 @@ extern class Krom {
|
|||||||
static function getConstantLocationCompute(shader: Dynamic, name: String): Dynamic;
|
static function getConstantLocationCompute(shader: Dynamic, name: String): Dynamic;
|
||||||
static function getTextureUnitCompute(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 compute(x: Int, y: Int, z: Int): Void;
|
||||||
static function viewportSetCamera(posX: Float, posY: Float, posZ: Float, rotX: Float, rotY: Float, rotZ: Float, rotW: Float): Void;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,7 +79,7 @@ class Display {
|
|||||||
public var frequency(get, never): Int;
|
public var frequency(get, never): Int;
|
||||||
|
|
||||||
function get_frequency(): Int {
|
function get_frequency(): Int {
|
||||||
return Krom.displayFrequency();
|
return 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
public var pixelsPerInch(get, never): Int;
|
public var pixelsPerInch(get, never): Int;
|
||||||
|
|||||||
@ -171,9 +171,8 @@ class SystemImpl {
|
|||||||
Krom.setGamepadAxisCallback(gamepadAxisCallback);
|
Krom.setGamepadAxisCallback(gamepadAxisCallback);
|
||||||
Krom.setGamepadButtonCallback(gamepadButtonCallback);
|
Krom.setGamepadButtonCallback(gamepadButtonCallback);
|
||||||
|
|
||||||
kha.audio2.Audio.samplesPerSecond = Krom.getSamplesPerSecond();
|
|
||||||
kha.audio1.Audio._init();
|
|
||||||
kha.audio2.Audio._init();
|
kha.audio2.Audio._init();
|
||||||
|
kha.audio1.Audio._init();
|
||||||
Krom.setAudioCallback(audioCallback);
|
Krom.setAudioCallback(audioCallback);
|
||||||
|
|
||||||
Scheduler.start();
|
Scheduler.start();
|
||||||
@ -208,7 +207,7 @@ class SystemImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function getRefreshRate(): Int {
|
public static function getRefreshRate(): Int {
|
||||||
return Krom.displayFrequency();
|
return 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getSystemId(): String {
|
public static function getSystemId(): String {
|
||||||
|
|||||||
@ -10,7 +10,8 @@ class Audio {
|
|||||||
|
|
||||||
public static function _init() {
|
public static function _init() {
|
||||||
var bufferSize = 1024 * 2;
|
var bufferSize = 1024 * 2;
|
||||||
buffer = new Buffer(bufferSize * 4, 2, samplesPerSecond);
|
buffer = new Buffer(bufferSize * 4, 2, 44100);
|
||||||
|
Audio.samplesPerSecond = 44100;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function _callCallback(samples: Int): Void {
|
public static function _callCallback(samples: Int): Void {
|
||||||
@ -31,11 +32,11 @@ class Audio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function _readSample(): FastFloat {
|
public static function _readSample(): Float {
|
||||||
if (buffer == null)
|
if (buffer == null)
|
||||||
return 0;
|
return 0;
|
||||||
var value = buffer.data.get(buffer.readLocation);
|
var value = buffer.data.get(buffer.readLocation);
|
||||||
++buffer.readLocation;
|
buffer.readLocation += 1;
|
||||||
if (buffer.readLocation >= buffer.size) {
|
if (buffer.readLocation >= buffer.size) {
|
||||||
buffer.readLocation = 0;
|
buffer.readLocation = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,7 +59,7 @@ class Graphics implements kha.graphics4.Graphics {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function refreshRate(): Int {
|
public function refreshRate(): Int {
|
||||||
return Krom.displayFrequency();
|
return 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clear(?color: Color, ?depth: Float, ?stencil: Int): Void {
|
public function clear(?color: Color, ?depth: Float, ?stencil: Int): Void {
|
||||||
|
|||||||
@ -51,7 +51,7 @@ class Scheduler {
|
|||||||
static var vsync: Bool;
|
static var vsync: Bool;
|
||||||
|
|
||||||
// Html5 target can update display frequency after some delay
|
// Html5 target can update display frequency after some delay
|
||||||
#if (kha_html5 || kha_debug_html5)
|
#if kha_html5
|
||||||
static var onedifhz(get, never): Float;
|
static var onedifhz(get, never): Float;
|
||||||
|
|
||||||
static inline function get_onedifhz(): Float {
|
static inline function get_onedifhz(): Float {
|
||||||
@ -97,7 +97,7 @@ class Scheduler {
|
|||||||
|
|
||||||
public static function start(restartTimers: Bool = false): Void {
|
public static function start(restartTimers: Bool = false): Void {
|
||||||
vsync = Window.get(0).vSynced;
|
vsync = Window.get(0).vSynced;
|
||||||
#if !(kha_html5 || kha_debug_html5)
|
#if !kha_html5
|
||||||
var hz = Display.primary != null ? Display.primary.frequency : 60;
|
var hz = Display.primary != null ? Display.primary.frequency : 60;
|
||||||
if (hz >= 57 && hz <= 63)
|
if (hz >= 57 && hz <= 63)
|
||||||
hz = 60;
|
hz = 60;
|
||||||
|
|||||||
BIN
Krom/Krom.exe
BIN
Krom/Krom.exe
Binary file not shown.
Binary file not shown.
@ -2,12 +2,10 @@
|
|||||||
-cp ../Kha/Backends/Krom
|
-cp ../Kha/Backends/Krom
|
||||||
-cp ../leenkx/Sources
|
-cp ../leenkx/Sources
|
||||||
-cp ../iron/Sources
|
-cp ../iron/Sources
|
||||||
-cp ../lib/aura/Sources
|
|
||||||
-cp ../lib/haxebullet/Sources
|
-cp ../lib/haxebullet/Sources
|
||||||
-cp ../lib/haxerecast/Sources
|
-cp ../lib/haxerecast/Sources
|
||||||
-cp ../lib/zui/Sources
|
-cp ../lib/zui/Sources
|
||||||
--macro include('iron', true, null, ['../iron/Sources'])
|
--macro include('iron', true, null, ['../iron/Sources'])
|
||||||
--macro include('aura', true, null, ['../lib/aura/Sources'])
|
|
||||||
--macro include('haxebullet', true, null, ['../lib/haxebullet/Sources'])
|
--macro include('haxebullet', true, null, ['../lib/haxebullet/Sources'])
|
||||||
--macro include('haxerecast', true, null, ['../lib/haxerecast/Sources'])
|
--macro include('haxerecast', true, null, ['../lib/haxerecast/Sources'])
|
||||||
--macro include('leenkx', true, ['leenkx.network'], ['../leenkx/Sources','../iron/Sources'])
|
--macro include('leenkx', true, ['leenkx.network'], ['../leenkx/Sources','../iron/Sources'])
|
||||||
|
|||||||
22
leenkx.py
22
leenkx.py
@ -24,7 +24,7 @@ import textwrap
|
|||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
import typing
|
import typing
|
||||||
from typing import Callable, Optional, List
|
from typing import Callable, Optional
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
@ -33,12 +33,6 @@ from bpy.props import *
|
|||||||
from bpy.types import Operator, AddonPreferences
|
from bpy.types import Operator, AddonPreferences
|
||||||
|
|
||||||
|
|
||||||
if bpy.app.version < (2, 90, 0):
|
|
||||||
ListType = List
|
|
||||||
else:
|
|
||||||
ListType = list
|
|
||||||
|
|
||||||
|
|
||||||
class SDKSource(IntEnum):
|
class SDKSource(IntEnum):
|
||||||
PREFS = 0
|
PREFS = 0
|
||||||
LOCAL = 1
|
LOCAL = 1
|
||||||
@ -79,7 +73,6 @@ def detect_sdk_path():
|
|||||||
area = win.screen.areas[0]
|
area = win.screen.areas[0]
|
||||||
area_type = area.type
|
area_type = area.type
|
||||||
area.type = "INFO"
|
area.type = "INFO"
|
||||||
if bpy.app.version >= (2, 92, 0):
|
|
||||||
with bpy.context.temp_override(window=win, screen=win.screen, area=area):
|
with bpy.context.temp_override(window=win, screen=win.screen, area=area):
|
||||||
bpy.ops.info.select_all(action='SELECT')
|
bpy.ops.info.select_all(action='SELECT')
|
||||||
bpy.ops.info.report_copy()
|
bpy.ops.info.report_copy()
|
||||||
@ -92,7 +85,6 @@ def detect_sdk_path():
|
|||||||
if match:
|
if match:
|
||||||
addon_prefs.sdk_path = os.path.dirname(match[-1])
|
addon_prefs.sdk_path = os.path.dirname(match[-1])
|
||||||
|
|
||||||
|
|
||||||
def get_link_web_server(self):
|
def get_link_web_server(self):
|
||||||
return self.get('link_web_server', 'http://localhost/')
|
return self.get('link_web_server', 'http://localhost/')
|
||||||
|
|
||||||
@ -318,9 +310,9 @@ class LeenkxAddonPreferences(AddonPreferences):
|
|||||||
layout.label(text="Welcome to Leenkx!")
|
layout.label(text="Welcome to Leenkx!")
|
||||||
|
|
||||||
# Compare version Blender and Leenkx (major, minor)
|
# Compare version Blender and Leenkx (major, minor)
|
||||||
if bpy.app.version[:2] not in [(4, 4), (4, 2), (3, 6), (3, 3)]:
|
if bpy.app.version[0] != 4 or bpy.app.version[1] != 2:
|
||||||
box = layout.box().column()
|
box = layout.box().column()
|
||||||
box.label(text="Warning: For Leenkx to work correctly, use a Blender LTS version")
|
box.label(text="Warning: For Leenkx to work correctly, use a Blender LTS version such as 4.2 | 3.6 | 3.3")
|
||||||
|
|
||||||
layout.prop(self, "sdk_path")
|
layout.prop(self, "sdk_path")
|
||||||
sdk_path = get_sdk_path(context)
|
sdk_path = get_sdk_path(context)
|
||||||
@ -566,7 +558,7 @@ def remove_readonly(func, path, excinfo):
|
|||||||
func(path)
|
func(path)
|
||||||
|
|
||||||
|
|
||||||
def run_proc(cmd: ListType[str], done: Optional[Callable[[bool], None]] = None):
|
def run_proc(cmd: list[str], done: Optional[Callable[[bool], None]] = None):
|
||||||
def fn(p, done):
|
def fn(p, done):
|
||||||
p.wait()
|
p.wait()
|
||||||
if done is not None:
|
if done is not None:
|
||||||
@ -847,12 +839,6 @@ def update_leenkx_py(sdk_path: str, force_relink=False):
|
|||||||
raise err
|
raise err
|
||||||
else:
|
else:
|
||||||
raise err
|
raise err
|
||||||
else:
|
|
||||||
if bpy.app.version < (2, 92, 0):
|
|
||||||
try:
|
|
||||||
lnx_module_file.unlink()
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
lnx_module_file.unlink(missing_ok=True)
|
lnx_module_file.unlink(missing_ok=True)
|
||||||
shutil.copy(Path(sdk_path) / 'leenkx.py', lnx_module_file)
|
shutil.copy(Path(sdk_path) / 'leenkx.py', lnx_module_file)
|
||||||
|
|||||||
@ -3,10 +3,6 @@
|
|||||||
|
|
||||||
#include "compiled.inc"
|
#include "compiled.inc"
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
|
||||||
uniform vec4 PPComp17;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
uniform vec2 dir;
|
uniform vec2 dir;
|
||||||
uniform vec2 screenSize;
|
uniform vec2 screenSize;
|
||||||
@ -49,12 +45,6 @@ void main() {
|
|||||||
res += factor * col;
|
res += factor * col;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
|
||||||
vec3 AirColor = vec3(PPComp17.x, PPComp17.y, PPComp17.z);
|
|
||||||
#else
|
|
||||||
vec3 AirColor = volumAirColor;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
res /= sumfactor;
|
res /= sumfactor;
|
||||||
fragColor = vec4(AirColor * res, 1.0);
|
fragColor = vec4(volumAirColor * res, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,11 +19,6 @@
|
|||||||
{
|
{
|
||||||
"name": "screenSize",
|
"name": "screenSize",
|
||||||
"link": "_screenSize"
|
"link": "_screenSize"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PPComp17",
|
|
||||||
"link": "_PPComp17",
|
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"texture_params": [],
|
"texture_params": [],
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
#ifdef _CPostprocess
|
||||||
uniform vec4 PPComp13;
|
uniform vec3 PPComp13;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
@ -14,7 +14,7 @@ out vec4 fragColor;
|
|||||||
vec2 barrelDistortion(vec2 coord, float amt) {
|
vec2 barrelDistortion(vec2 coord, float amt) {
|
||||||
vec2 cc = coord - 0.5;
|
vec2 cc = coord - 0.5;
|
||||||
float dist = dot(cc, cc);
|
float dist = dot(cc, cc);
|
||||||
return coord - cc * dist * amt;
|
return coord + cc * dist * amt;
|
||||||
}
|
}
|
||||||
float sat(float value)
|
float sat(float value)
|
||||||
{
|
{
|
||||||
@ -43,19 +43,17 @@ void main() {
|
|||||||
#ifdef _CPostprocess
|
#ifdef _CPostprocess
|
||||||
float max_distort = PPComp13.x;
|
float max_distort = PPComp13.x;
|
||||||
int num_iter = int(PPComp13.y);
|
int num_iter = int(PPComp13.y);
|
||||||
int CAType = int(PPComp13.z);
|
|
||||||
int on = int(PPComp13.w);
|
|
||||||
#else
|
#else
|
||||||
float max_distort = compoChromaticStrength;
|
float max_distort = compoChromaticStrength;
|
||||||
int num_iter = compoChromaticSamples;
|
int num_iter = compoChromaticSamples;
|
||||||
int CAType = compoChromaticType;
|
|
||||||
int on = 1;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Spectral
|
// Spectral
|
||||||
if (CAType == 1) {
|
if (compoChromaticType == 1) {
|
||||||
float reci_num_iter_f = 1.0 / float(num_iter);
|
float reci_num_iter_f = 1.0 / float(num_iter);
|
||||||
|
|
||||||
|
vec2 resolution = vec2(1,1);
|
||||||
|
vec2 uv = (texCoord.xy/resolution.xy);
|
||||||
vec4 sumcol = vec4(0.0);
|
vec4 sumcol = vec4(0.0);
|
||||||
vec4 sumw = vec4(0.0);
|
vec4 sumw = vec4(0.0);
|
||||||
for (int i=0; i < num_iter; ++i)
|
for (int i=0; i < num_iter; ++i)
|
||||||
@ -63,21 +61,18 @@ void main() {
|
|||||||
float t = float(i) * reci_num_iter_f;
|
float t = float(i) * reci_num_iter_f;
|
||||||
vec4 w = spectrum_offset(t);
|
vec4 w = spectrum_offset(t);
|
||||||
sumw += w;
|
sumw += w;
|
||||||
vec2 distortedUV = barrelDistortion(texCoord, 0.6 * max_distort * t);
|
sumcol += w * texture(tex, barrelDistortion(uv, 0.6 * max_distort * t));
|
||||||
sumcol += w * texture(tex, distortedUV);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (on == 1) fragColor = sumcol / sumw; else fragColor = texture(tex, texCoord);
|
fragColor = sumcol / sumw;
|
||||||
}
|
}
|
||||||
|
|
||||||
// inward sampling to avoid edge artifacts
|
// Simple
|
||||||
else {
|
else {
|
||||||
vec3 col = vec3(0.0);
|
vec3 col = vec3(0.0);
|
||||||
vec2 toCenter = (vec2(0.5) - texCoord) * max_distort / 500.0;
|
col.x = texture(tex, texCoord + ((vec2(0.0, 1.0) * max_distort) / vec2(1000.0))).x;
|
||||||
col.x = texture(tex, texCoord + toCenter * 0.0).x;
|
col.y = texture(tex, texCoord + ((vec2(-0.85, -0.5) * max_distort) / vec2(1000.0))).y;
|
||||||
col.y = texture(tex, texCoord + toCenter * 0.5).y;
|
col.z = texture(tex, texCoord + ((vec2(0.85, -0.5) * max_distort) / vec2(1000.0))).z;
|
||||||
col.z = texture(tex, texCoord + toCenter * 1.0).z;
|
fragColor = vec4(col.x, col.y, col.z, fragColor.w);
|
||||||
if (on == 1) fragColor = vec4(col.x, col.y, col.z, 1.0);
|
|
||||||
else fragColor = texture(tex, texCoord);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,5 +5,5 @@ out vec4 fragColor;
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
fragColor = vec4(0.0,0.0,0.0,1.0);
|
fragColor = vec4(0.0,0.0,0.0,1.0);
|
||||||
gl_FragDepth = 1.0;
|
gl_FragDepth = 0.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,5 +4,5 @@ in vec2 texCoord;
|
|||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_FragDepth = 1.0;
|
gl_FragDepth = 0.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,11 +62,8 @@ uniform vec3 PPComp5;
|
|||||||
uniform vec3 PPComp6;
|
uniform vec3 PPComp6;
|
||||||
uniform vec3 PPComp7;
|
uniform vec3 PPComp7;
|
||||||
uniform vec3 PPComp8;
|
uniform vec3 PPComp8;
|
||||||
uniform vec3 PPComp11;
|
|
||||||
uniform vec3 PPComp14;
|
uniform vec3 PPComp14;
|
||||||
uniform vec4 PPComp15;
|
uniform vec4 PPComp15;
|
||||||
uniform vec4 PPComp16;
|
|
||||||
uniform vec4 PPComp18;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// #ifdef _CPos
|
// #ifdef _CPos
|
||||||
@ -109,16 +106,6 @@ in vec2 texCoord;
|
|||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
#ifdef _CFog
|
#ifdef _CFog
|
||||||
#ifdef _CPostprocess
|
|
||||||
vec3 FogColor = vec3(PPComp18.x, PPComp18.y, PPComp18.z);
|
|
||||||
float FogAmountA = PPComp18.w;
|
|
||||||
float FogAmountB = PPComp11.z;
|
|
||||||
#else
|
|
||||||
vec3 FogColor = compoFogColor;
|
|
||||||
float FogAmountA = compoFogAmountA;
|
|
||||||
float FogAmountB = compoFogAmountB;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// const vec3 compoFogColor = vec3(0.5, 0.6, 0.7);
|
// const vec3 compoFogColor = vec3(0.5, 0.6, 0.7);
|
||||||
// const float compoFogAmountA = 1.0; // b = 0.01
|
// const float compoFogAmountA = 1.0; // b = 0.01
|
||||||
// const float compoFogAmountB = 1.0; // c = 0.1
|
// const float compoFogAmountB = 1.0; // c = 0.1
|
||||||
@ -131,8 +118,8 @@ out vec4 fragColor;
|
|||||||
// }
|
// }
|
||||||
vec3 applyFog(vec3 rgb, float distance) {
|
vec3 applyFog(vec3 rgb, float distance) {
|
||||||
// float fogAmount = 1.0 - exp(-distance * compoFogAmountA);
|
// float fogAmount = 1.0 - exp(-distance * compoFogAmountA);
|
||||||
float fogAmount = 1.0 - exp(-distance * (FogAmountA / 100));
|
float fogAmount = 1.0 - exp(-distance * (compoFogAmountA / 100));
|
||||||
return mix(rgb, FogColor, fogAmount);
|
return mix(rgb, compoFogColor, fogAmount);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -144,7 +131,7 @@ float ConvertEV100ToExposure(float EV100) {
|
|||||||
return 1/0.8 * exp2(-EV100);
|
return 1/0.8 * exp2(-EV100);
|
||||||
}
|
}
|
||||||
float ComputeEV(float avgLuminance) {
|
float ComputeEV(float avgLuminance) {
|
||||||
const float sqAperture = PPComp1.x * PPComp1.x;
|
const float sqAperture = PPComp1[0].x * PPComp1.x;
|
||||||
const float shutterTime = 1.0 / PPComp1.y;
|
const float shutterTime = 1.0 / PPComp1.y;
|
||||||
const float ISO = PPComp1.z;
|
const float ISO = PPComp1.z;
|
||||||
const float EC = PPComp2.x;
|
const float EC = PPComp2.x;
|
||||||
@ -358,32 +345,20 @@ void main() {
|
|||||||
fragColor = textureLod(tex, texCo, 0.0);
|
fragColor = textureLod(tex, texCo, 0.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: re-investigate white artifacts
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _CSharpen
|
#ifdef _CSharpen
|
||||||
#ifdef _CPostprocess
|
#ifdef _CPostprocess
|
||||||
float strengthSharpen = PPComp14.y;
|
float strengthSharpen = PPComp14.y;
|
||||||
vec3 SharpenColor = vec3(PPComp16.x, PPComp16.y, PPComp16.z);
|
|
||||||
float SharpenSize = PPComp16.w;
|
|
||||||
#else
|
#else
|
||||||
float strengthSharpen = compoSharpenStrength;
|
float strengthSharpen = compoSharpenStrength;
|
||||||
vec3 SharpenColor = compoSharpenColor;
|
|
||||||
float SharpenSize = compoSharpenSize;
|
|
||||||
#endif
|
#endif
|
||||||
vec3 col1 = textureLod(tex, texCo + vec2(-texStep.x, -texStep.y) * SharpenSize, 0.0).rgb;
|
vec3 col1 = textureLod(tex, texCo + vec2(-texStep.x, -texStep.y) * 1.5, 0.0).rgb;
|
||||||
vec3 col2 = textureLod(tex, texCo + vec2(texStep.x, -texStep.y) * SharpenSize, 0.0).rgb;
|
vec3 col2 = textureLod(tex, texCo + vec2(texStep.x, -texStep.y) * 1.5, 0.0).rgb;
|
||||||
vec3 col3 = textureLod(tex, texCo + vec2(-texStep.x, texStep.y) * SharpenSize, 0.0).rgb;
|
vec3 col3 = textureLod(tex, texCo + vec2(-texStep.x, texStep.y) * 1.5, 0.0).rgb;
|
||||||
vec3 col4 = textureLod(tex, texCo + vec2(texStep.x, texStep.y) * SharpenSize, 0.0).rgb;
|
vec3 col4 = textureLod(tex, texCo + vec2(texStep.x, texStep.y) * 1.5, 0.0).rgb;
|
||||||
vec3 colavg = (col1 + col2 + col3 + col4) * 0.25;
|
vec3 colavg = (col1 + col2 + col3 + col4) * 0.25;
|
||||||
|
fragColor.rgb += (fragColor.rgb - colavg) * strengthSharpen;
|
||||||
float edgeMagnitude = length(fragColor.rgb - colavg);
|
|
||||||
fragColor.rgb = mix(fragColor.rgb, SharpenColor, min(edgeMagnitude * strengthSharpen * 2.0, 1.0));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _CFog
|
#ifdef _CFog
|
||||||
@ -432,25 +407,16 @@ void main() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _CExposure
|
#ifdef _CExposure
|
||||||
#ifdef _CPostprocess
|
|
||||||
fragColor.rgb+=fragColor.rgb*PPComp8.x;
|
|
||||||
#else
|
|
||||||
fragColor.rgb += fragColor.rgb * compoExposureStrength;
|
fragColor.rgb += fragColor.rgb * compoExposureStrength;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
#ifdef _CPostprocess
|
||||||
fragColor.rgb *= ComputeEV(0.0);
|
fragColor.rgb *= ComputeEV(0.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _AutoExposure
|
#ifdef _AutoExposure
|
||||||
#ifdef _CPostprocess
|
|
||||||
float AEStrength = PPComp8.y;
|
|
||||||
#else
|
|
||||||
float AEStrength = autoExposureStrength;
|
|
||||||
#endif
|
|
||||||
float expo = 2.0 - clamp(length(textureLod(histogram, vec2(0.5, 0.5), 0).rgb), 0.0, 1.0);
|
float expo = 2.0 - clamp(length(textureLod(histogram, vec2(0.5, 0.5), 0).rgb), 0.0, 1.0);
|
||||||
fragColor.rgb *= pow(expo, AEStrength * 2.0);
|
fragColor.rgb *= pow(expo, autoExposureStrength * 2.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Clamp color to get rid of INF values that don't work for the tone mapping below
|
// Clamp color to get rid of INF values that don't work for the tone mapping below
|
||||||
@ -514,7 +480,9 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5);
|
|||||||
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
|
||||||
} else if (PPComp4.x == 10){
|
} else if (PPComp4.x == 10){
|
||||||
fragColor.rgb = tonemapAgXFull(fragColor.rgb);
|
fragColor.rgb = tonemapAgXFull(fragColor.rgb);
|
||||||
} //else { fragColor.rgb = vec3(0,1,0); //ERROR}
|
} else {
|
||||||
|
fragColor.rgb = vec3(0,1,0); //ERROR
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -235,16 +235,6 @@
|
|||||||
"name": "PPComp15",
|
"name": "PPComp15",
|
||||||
"link": "_PPComp15",
|
"link": "_PPComp15",
|
||||||
"ifdef": ["_CPostprocess"]
|
"ifdef": ["_CPostprocess"]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PPComp16",
|
|
||||||
"link": "_PPComp16",
|
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PPComp18",
|
|
||||||
"link": "_PPComp18",
|
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"texture_params": [],
|
"texture_params": [],
|
||||||
|
|||||||
@ -2,12 +2,10 @@
|
|||||||
|
|
||||||
#include "compiled.inc"
|
#include "compiled.inc"
|
||||||
#include "std/gbuffer.glsl"
|
#include "std/gbuffer.glsl"
|
||||||
|
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
#include "std/clusters.glsl"
|
#include "std/clusters.glsl"
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Irr
|
|
||||||
#include "std/shirr.glsl"
|
|
||||||
#endif
|
|
||||||
#ifdef _SSS
|
#ifdef _SSS
|
||||||
#include "std/sss.glsl"
|
#include "std/sss.glsl"
|
||||||
#endif
|
#endif
|
||||||
@ -15,9 +13,26 @@
|
|||||||
#include "std/ssrs.glsl"
|
#include "std/ssrs.glsl"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform sampler2D gbufferD;
|
// Environment map
|
||||||
uniform sampler2D gbuffer0;
|
uniform float envmapStrength;
|
||||||
uniform sampler2D gbuffer1;
|
#ifdef _Irr
|
||||||
|
uniform vec4 shirr[7];
|
||||||
|
uniform float ambientIntensity;
|
||||||
|
#include "std/shirr.glsl"
|
||||||
|
#endif
|
||||||
|
#include "std/environment_sample.glsl"
|
||||||
|
#include "std/light.glsl"
|
||||||
|
|
||||||
|
// Gbuffer
|
||||||
|
//uniform sampler2D depthtex; // Raw depth
|
||||||
|
uniform sampler2D gbufferD; // Depth (cheap)
|
||||||
|
uniform sampler2D gbuffer0; // Normal/Metal
|
||||||
|
uniform sampler2D gbuffer1; // Albedo
|
||||||
|
|
||||||
|
uniform vec2 cameraProj;
|
||||||
|
uniform vec3 eye;
|
||||||
|
uniform vec3 eyeLook;
|
||||||
|
uniform mat4 invVP;
|
||||||
|
|
||||||
#ifdef _gbuffer2
|
#ifdef _gbuffer2
|
||||||
uniform sampler2D gbuffer2;
|
uniform sampler2D gbuffer2;
|
||||||
@ -29,21 +44,16 @@ uniform sampler2D gbuffer1;
|
|||||||
#ifdef _VoxelGI
|
#ifdef _VoxelGI
|
||||||
uniform sampler2D voxels_diffuse;
|
uniform sampler2D voxels_diffuse;
|
||||||
uniform sampler2D voxels_specular;
|
uniform sampler2D voxels_specular;
|
||||||
#else
|
#endif
|
||||||
#ifdef _VoxelAOvar
|
#ifdef _VoxelAOvar
|
||||||
uniform sampler2D voxels_ao;
|
uniform sampler2D voxels_ao;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
uniform sampler3D voxels;
|
uniform sampler3D voxels;
|
||||||
uniform sampler3D voxelsSDF;
|
uniform sampler3D voxelsSDF;
|
||||||
uniform float clipmaps[10 * voxelgiClipmapCount];
|
uniform float clipmaps[10 * voxelgiClipmapCount];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform float envmapStrength;
|
|
||||||
#ifdef _Irr
|
|
||||||
uniform vec4 shirr[7];
|
|
||||||
#endif
|
|
||||||
#ifdef _Brdf
|
#ifdef _Brdf
|
||||||
uniform sampler2D senvmapBrdf;
|
uniform sampler2D senvmapBrdf;
|
||||||
#endif
|
#endif
|
||||||
@ -59,19 +69,10 @@ uniform vec3 backgroundCol;
|
|||||||
uniform sampler2D ssaotex;
|
uniform sampler2D ssaotex;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _SSGI
|
|
||||||
uniform sampler2D ssgitex;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _SSS
|
#ifdef _SSS
|
||||||
uniform vec2 lightPlane;
|
uniform vec2 lightPlane;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _SSRS
|
|
||||||
//!uniform mat4 VP;
|
|
||||||
uniform mat4 invVP;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LightIES
|
#ifdef _LightIES
|
||||||
//!uniform sampler2D texIES;
|
//!uniform sampler2D texIES;
|
||||||
#endif
|
#endif
|
||||||
@ -101,25 +102,6 @@ uniform mat4 invVP;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform vec2 cameraProj;
|
|
||||||
#ifdef _VRStereo
|
|
||||||
uniform vec3 eye; // center camera position
|
|
||||||
uniform vec3 eyeLook; // center camera look
|
|
||||||
uniform vec3 eyeLeft;
|
|
||||||
uniform vec3 eyeRight;
|
|
||||||
uniform vec3 eyeLookLeft;
|
|
||||||
uniform vec3 eyeLookRight;
|
|
||||||
uniform mat4 invVPLeft;
|
|
||||||
uniform mat4 invVPRight;
|
|
||||||
#ifdef _SinglePoint
|
|
||||||
uniform vec3 pointPosLeft;
|
|
||||||
uniform vec3 pointPosRight;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
uniform vec3 eye;
|
|
||||||
uniform vec3 eyeLook;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
uniform vec4 lightsArray[maxLights * 3];
|
uniform vec4 lightsArray[maxLights * 3];
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
@ -133,15 +115,11 @@ uniform vec2 cameraPlane;
|
|||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
//!uniform sampler2DShadow shadowMapSpot[1];
|
//!uniform sampler2DShadow shadowMapSpot[1];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
//!uniform sampler2D shadowMapSpotTransparent[1];
|
//!uniform sampler2D shadowMapSpotTransparent[1];
|
||||||
#endif
|
|
||||||
//!uniform mat4 LWVPSpot[1];
|
//!uniform mat4 LWVPSpot[1];
|
||||||
#else
|
#else
|
||||||
//!uniform samplerCubeShadow shadowMapPoint[1];
|
//!uniform samplerCubeShadow shadowMapPoint[1];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
//!uniform samplerCube shadowMapPointTransparent[1];
|
//!uniform samplerCube shadowMapPointTransparent[1];
|
||||||
#endif
|
|
||||||
//!uniform vec2 lightProj;
|
//!uniform vec2 lightProj;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -149,40 +127,30 @@ uniform vec2 cameraPlane;
|
|||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
#ifdef _SingleAtlas
|
#ifdef _SingleAtlas
|
||||||
uniform sampler2DShadow shadowMapAtlas;
|
uniform sampler2DShadow shadowMapAtlas;
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapAtlasTransparent;
|
uniform sampler2D shadowMapAtlasTransparent;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
//!uniform sampler2DShadow shadowMapAtlasPoint;
|
//!uniform sampler2DShadow shadowMapAtlasPoint;
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
//!uniform sampler2D shadowMapAtlasPointTransparent;
|
//!uniform sampler2D shadowMapAtlasPointTransparent;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
//!uniform vec4 pointLightDataArray[4];
|
||||||
//!uniform vec4 pointLightDataArray[maxLightsCluster * 6];
|
|
||||||
#else
|
#else
|
||||||
//!uniform samplerCubeShadow shadowMapPoint[4];
|
//!uniform samplerCubeShadow shadowMapPoint[4];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
//!uniform samplerCube shadowMapPointTransparent[4];
|
//!uniform samplerCube shadowMapPointTransparent[4];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
//!uniform vec2 lightProj;
|
//!uniform vec2 lightProj;
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
//!uniform sampler2DShadow shadowMapAtlasSpot;
|
//!uniform sampler2DShadow shadowMapAtlasSpot;
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
//!uniform sampler2D shadowMapAtlasSpotTransparent;
|
//!uniform sampler2D shadowMapAtlasSpotTransparent;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
//!uniform sampler2DShadow shadowMapSpot[4];
|
//!uniform sampler2DShadow shadowMapSpot[4];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
//!uniform sampler2D shadowMapSpotTransparent[4];
|
//!uniform sampler2D shadowMapSpotTransparent[4];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
//!uniform mat4 LWVPSpotArray[maxLightsCluster];
|
//!uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -195,16 +163,12 @@ uniform vec3 sunCol;
|
|||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
uniform sampler2DShadow shadowMapAtlasSun;
|
uniform sampler2DShadow shadowMapAtlasSun;
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapAtlasSunTransparent;
|
uniform sampler2D shadowMapAtlasSunTransparent;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
uniform sampler2DShadow shadowMap;
|
uniform sampler2DShadow shadowMap;
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapTransparent;
|
uniform sampler2D shadowMapTransparent;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
uniform float shadowsBias;
|
uniform float shadowsBias;
|
||||||
#ifdef _CSM
|
#ifdef _CSM
|
||||||
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
|
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
|
||||||
@ -215,9 +179,7 @@ uniform vec3 sunCol;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _SinglePoint // Fast path for single light
|
#ifdef _SinglePoint // Fast path for single light
|
||||||
#ifndef _VRStereo
|
|
||||||
uniform vec3 pointPos;
|
uniform vec3 pointPos;
|
||||||
#endif
|
|
||||||
uniform vec3 pointCol;
|
uniform vec3 pointCol;
|
||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
uniform float pointBias;
|
uniform float pointBias;
|
||||||
@ -241,9 +203,8 @@ in vec3 viewRay;
|
|||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
fragColor = vec4(0.0);
|
||||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
|
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
|
||||||
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
|
|
||||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
|
||||||
|
|
||||||
vec3 n;
|
vec3 n;
|
||||||
n.z = 1.0 - abs(g0.x) - abs(g0.y);
|
n.z = 1.0 - abs(g0.x) - abs(g0.y);
|
||||||
@ -255,72 +216,54 @@ void main() {
|
|||||||
uint matid;
|
uint matid;
|
||||||
unpackFloatInt16(g0.a, metallic, matid);
|
unpackFloatInt16(g0.a, metallic, matid);
|
||||||
|
|
||||||
|
vec4 g1 = textureLod(gbuffer1, texCoord, 0.0); // Basecolor.rgb, spec/occ
|
||||||
vec2 occspec = unpackFloat2(g1.a);
|
vec2 occspec = unpackFloat2(g1.a);
|
||||||
// re-investigate clamp basecolor to prevent extreme values causing glitches
|
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
|
||||||
vec3 basecolor = min(g1.rgb, vec3(2.0));
|
vec3 f0 = surfaceF0(g1.rgb, metallic);
|
||||||
vec3 albedo = surfaceAlbedo(basecolor, metallic);
|
vec3 envl = vec3(0.0);
|
||||||
vec3 f0 = surfaceF0(basecolor, metallic);
|
|
||||||
|
|
||||||
#ifdef _VRStereo
|
// world-space position:
|
||||||
bool isLeftEye = texCoord.x < 0.5;
|
float rawDepth = textureLod(gbufferD, texCoord, 0.0).r;
|
||||||
vec3 eyePos = isLeftEye ? eyeLeft : eyeRight;
|
float clipZ = rawDepth * 2.0 - 1.0; // depth -> clip-space
|
||||||
mat4 invVP_eye = isLeftEye ? invVPLeft : invVPRight;
|
vec4 clipPos = vec4(texCoord * 2.0 - 1.0, clipZ, 1.0);
|
||||||
|
vec4 worldPos = invVP * clipPos;
|
||||||
vec2 eyeTexCoord = vec2(
|
vec3 p = worldPos.xyz / worldPos.w;
|
||||||
isLeftEye ? texCoord.x * 2.0 : (texCoord.x - 0.5) * 2.0,
|
|
||||||
texCoord.y
|
|
||||||
);
|
|
||||||
|
|
||||||
vec3 p = getPos2(invVP_eye, depth, eyeTexCoord);
|
|
||||||
vec3 v = normalize(eyePos - p);
|
|
||||||
#else
|
|
||||||
vec3 p = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
|
|
||||||
vec3 v = normalize(eye - p);
|
vec3 v = normalize(eye - p);
|
||||||
#endif
|
|
||||||
float dotNV = max(dot(n, v), 0.0);
|
float dotNV = max(dot(n, v), 0.0);
|
||||||
|
|
||||||
|
// view-space vector for reflection
|
||||||
|
vec3 viewPos = getPosView(viewRay, rawDepth, cameraProj);
|
||||||
|
vec3 viewDir = normalize(-viewPos);
|
||||||
|
|
||||||
#ifdef _gbuffer2
|
#ifdef _gbuffer2
|
||||||
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
|
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef _MicroShadowing
|
#ifdef _MicroShadowing
|
||||||
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
|
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _Brdf
|
#ifdef _Brdf
|
||||||
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
|
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
|
||||||
vec3 F = f0 * envBRDF.x + envBRDF.y;
|
|
||||||
#else
|
|
||||||
vec3 F = f0;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _VoxelAOvar
|
|
||||||
#ifndef _VoxelGI
|
|
||||||
// Envmap
|
|
||||||
#ifdef _Irr
|
#ifdef _Irr
|
||||||
vec3 envl = shIrradiance(n, shirr);
|
// Sample ambient diffuse lighting
|
||||||
|
vec3 ambient = sampleDiffuseEnvironment(n);
|
||||||
|
|
||||||
#ifdef _gbuffer2
|
#ifdef _gbuffer2
|
||||||
if (g2.b < 0.5) {
|
if (g2.b >= 0.5) {
|
||||||
envl = envl;
|
ambient = vec3(0.0); // Mask it if g2 says this surface wants no ambient lighting
|
||||||
} else {
|
|
||||||
envl = vec3(0.0);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _EnvTex
|
fragColor.rgb += ambient * ambientIntensity;
|
||||||
envl /= PI;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
vec3 envl = vec3(0.0);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _Rad
|
#ifdef _Rad
|
||||||
vec3 reflectionWorld = reflect(-v, n);
|
vec3 reflectionWorld = reflect(-v, n);
|
||||||
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
|
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
|
||||||
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
|
||||||
prefilteredColor = min(prefilteredColor, vec3(20.0));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _EnvLDR
|
#ifdef _EnvLDR
|
||||||
@ -333,53 +276,61 @@ void main() {
|
|||||||
envl.rgb *= albedo;
|
envl.rgb *= albedo;
|
||||||
|
|
||||||
#ifdef _Brdf
|
#ifdef _Brdf
|
||||||
envl.rgb *= 1.0 - F; //LV: We should take refracted light into account
|
envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); //LV: We should take refracted light into account
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _Rad // Indirect specular
|
#ifdef _Rad // Indirect specular
|
||||||
envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT
|
envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT
|
||||||
#else
|
#else
|
||||||
#ifdef _EnvCol
|
#ifdef _EnvCol
|
||||||
envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0?
|
envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); //LV: Eh, what's the point of weighting it only by F0?
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
envl.rgb *= envmapStrength * occspec.x;
|
envl.rgb *= envmapStrength * occspec.x;
|
||||||
|
|
||||||
fragColor.rgb = envl;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _VoxelGI
|
#ifdef _VoxelGI
|
||||||
fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff;
|
vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0);
|
||||||
|
fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff;
|
||||||
if(roughness < 1.0 && occspec.y > 0.0)
|
if(roughness < 1.0 && occspec.y > 0.0)
|
||||||
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl;
|
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
#ifdef _VoxelAOvar
|
#ifdef _VoxelAOvar
|
||||||
fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc;
|
envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// if voxel GI isn't enabled, we fall back to SSR (SSR also processes indirect)
|
||||||
|
#ifndef _VoxelGI
|
||||||
|
fragColor.rgb += envl;
|
||||||
|
#ifndef _SSR
|
||||||
|
// if SSR is disabled, we fallback to simple environment texture
|
||||||
|
vec3 fallbackEnvColor = sampleSpecularEnvironment(reflect(viewDir, n), roughness);
|
||||||
|
fragColor.rgb += fallbackEnvColor;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// show voxel GI
|
||||||
|
#ifdef _VoxelGI
|
||||||
// Show voxels
|
// Show voxels
|
||||||
// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99);
|
vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99);
|
||||||
// vec3 direction = vec3(0.0, 0.0, -1.0);
|
vec3 direction = vec3(0.0, 0.0, -1.0);
|
||||||
// vec4 color = vec4(0.0f);
|
vec4 color = vec4(0.0f);
|
||||||
// for(uint step = 0; step < 400 && color.a < 0.99f; ++step) {
|
for(uint step = 0; step < 400 && color.a < 0.99f; ++step) {
|
||||||
// vec3 point = origin + 0.005 * step * direction;
|
vec3 point = origin + 0.005 * step * direction;
|
||||||
// color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0);
|
color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0);
|
||||||
// }
|
}
|
||||||
// fragColor.rgb += color.rgb;
|
fragColor.rgb += color.rgb;
|
||||||
|
|
||||||
// Show SSAO
|
|
||||||
// fragColor.rgb = texture(ssaotex, texCoord).rrr;
|
|
||||||
|
|
||||||
#ifdef _SSAO
|
|
||||||
fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _SSGI
|
// show SSAO
|
||||||
vec3 ssgiColor = textureLod(ssgitex, texCoord, 0.0).rgb;
|
#ifdef _SSAO
|
||||||
fragColor.rgb += ssgiColor * albedo;
|
fragColor.rgb = texture(ssaotex, texCoord).rrr;
|
||||||
|
// #ifdef _RTGI
|
||||||
|
// fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).rgb;
|
||||||
|
// #else
|
||||||
|
fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r;
|
||||||
|
// #endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _EmissionShadeless
|
#ifdef _EmissionShadeless
|
||||||
@ -413,67 +364,37 @@ void main() {
|
|||||||
#ifdef _CSM
|
#ifdef _CSM
|
||||||
svisibility = shadowTestCascade(
|
svisibility = shadowTestCascade(
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
shadowMapAtlasSun, shadowMapAtlasSunTransparent
|
shadowMapAtlasSun, shadowMapAtlasSunTransparent
|
||||||
#else
|
#else
|
||||||
shadowMapAtlas, shadowMapAtlasTransparent
|
shadowMapAtlas, shadowMapAtlasTransparent
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifndef _SingleAtlas
|
|
||||||
shadowMapAtlasSun
|
|
||||||
#else
|
|
||||||
shadowMapAtlas
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
shadowMap, shadowMapTransparent
|
shadowMap, shadowMapTransparent
|
||||||
#else
|
|
||||||
shadowMap
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
, eye, p + n * shadowsBias * 2, shadowsBias
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, false
|
|
||||||
#endif
|
#endif
|
||||||
|
, eye, p + n * shadowsBias * 10, shadowsBias, false
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 2, 1.0);
|
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
|
||||||
if (lPos.w > 0.0) {
|
if (lPos.w > 0.0) {
|
||||||
svisibility = shadowTest(
|
svisibility = shadowTest(
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
shadowMapAtlasSun, shadowMapAtlasSunTransparent
|
shadowMapAtlasSun, shadowMapAtlasSunTransparent
|
||||||
#else
|
#else
|
||||||
shadowMapAtlas, shadowMapAtlasTransparent
|
shadowMapAtlas, shadowMapAtlasTransparent
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifndef _SingleAtlas
|
|
||||||
shadowMapAtlasSun
|
|
||||||
#else
|
|
||||||
shadowMapAtlas
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
shadowMap, shadowMapTransparent
|
shadowMap, shadowMapTransparent
|
||||||
#else
|
|
||||||
shadowMap
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
, lPos.xyz / lPos.w, shadowsBias
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, false
|
|
||||||
#endif
|
#endif
|
||||||
|
, lPos.xyz / lPos.w, shadowsBias, false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, -g2.rg).r) * voxelgiShad;
|
svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _SSRS
|
#ifdef _SSRS
|
||||||
@ -529,25 +450,16 @@ void main() {
|
|||||||
|
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
|
|
||||||
#ifdef _VRStereo
|
|
||||||
vec3 lightPos = pointPosLeft;
|
|
||||||
#else
|
|
||||||
vec3 lightPos = pointPos;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fragColor.rgb += sampleLight(
|
fragColor.rgb += sampleLight(
|
||||||
p, n, v, dotNV, lightPos, pointCol, albedo, roughness, occspec.y, f0
|
p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0
|
||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
, 0, pointBias, true
|
, 0, pointBias, true, false
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, false
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight
|
, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight
|
||||||
#endif
|
#endif
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
, voxels, voxelsSDF, clipmaps, -g2.rg
|
, voxels, voxelsSDF, clipmaps
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MicroShadowing
|
#ifdef _MicroShadowing
|
||||||
, occspec.x
|
, occspec.x
|
||||||
@ -559,16 +471,15 @@ void main() {
|
|||||||
|
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
#ifdef _SSS
|
#ifdef _SSS
|
||||||
#ifdef _ShadowMap
|
if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot[0], p, n, normalize(pointPos - p), lightPlane.y, shadowMapSpot[0]);//TODO implement transparent shadowmaps into the SSSSTransmittance()
|
||||||
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()
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
float viewz = linearize(depth * 0.5 + 0.5, cameraProj);
|
// compute depth for clustering: use the view-space Z component (linearized depth)
|
||||||
|
float viewz = viewPos.z;
|
||||||
int clusterI = getClusterI(texCoord, viewz, cameraPlane);
|
int clusterI = getClusterI(texCoord, viewz, cameraPlane);
|
||||||
int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);
|
int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);
|
||||||
|
|
||||||
@ -596,10 +507,7 @@ void main() {
|
|||||||
f0
|
f0
|
||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
// light index, shadow bias, cast_shadows
|
// light index, shadow bias, cast_shadows
|
||||||
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0
|
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, false
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
, lightsArray[li * 3 + 2].y != 0.0
|
, lightsArray[li * 3 + 2].y != 0.0
|
||||||
@ -610,11 +518,12 @@ void main() {
|
|||||||
, lightsArraySpot[li * 2 + 1].xyz // right
|
, lightsArraySpot[li * 2 + 1].xyz // right
|
||||||
#endif
|
#endif
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
, voxels, voxelsSDF, clipmaps, -g2.rg
|
, voxels, voxelsSDF, clipmaps
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MicroShadowing
|
#ifdef _MicroShadowing
|
||||||
, occspec.x
|
, occspec.x
|
||||||
#endif
|
#endif
|
||||||
|
// TODO: Cleanup. Probably broken
|
||||||
#ifdef _SSRS
|
#ifdef _SSRS
|
||||||
, gbufferD, invVP, eye
|
, gbufferD, invVP, eye
|
||||||
#endif
|
#endif
|
||||||
@ -622,10 +531,13 @@ void main() {
|
|||||||
}
|
}
|
||||||
#endif // _Clusters
|
#endif // _Clusters
|
||||||
|
|
||||||
fragColor.rgb = clamp(fragColor.rgb, vec3(0.0), vec3(65504.0));
|
/*
|
||||||
if (any(isnan(fragColor.rgb)) || any(isinf(fragColor.rgb))) {
|
#ifdef _VoxelRefract
|
||||||
fragColor.rgb = vec3(0.0);
|
if(opac < 1.0) {
|
||||||
|
vec3 refraction = traceRefraction(p, n, voxels, v, ior, roughness, eye) * voxelgiRefr;
|
||||||
|
fragColor.rgb = mix(refraction, fragColor.rgb, opac);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
fragColor.a = 1.0; // Mark as opaque
|
fragColor.a = 1.0; // Mark as opaque
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,36 +20,6 @@
|
|||||||
"name": "eyeLook",
|
"name": "eyeLook",
|
||||||
"link": "_cameraLook"
|
"link": "_cameraLook"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "eyeLeft",
|
|
||||||
"link": "_eyeLeft",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "eyeRight",
|
|
||||||
"link": "_eyeRight",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "eyeLookLeft",
|
|
||||||
"link": "_eyeLookLeft",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "eyeLookRight",
|
|
||||||
"link": "_eyeLookRight",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invVPLeft",
|
|
||||||
"link": "_inverseViewProjectionMatrixLeft",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invVPRight",
|
|
||||||
"link": "_inverseViewProjectionMatrixRight",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "clipmaps",
|
"name": "clipmaps",
|
||||||
"link": "_clipmaps",
|
"link": "_clipmaps",
|
||||||
@ -79,10 +49,6 @@
|
|||||||
"link": "$brdf.png",
|
"link": "$brdf.png",
|
||||||
"ifdef": ["_Brdf"]
|
"ifdef": ["_Brdf"]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "cameraProj",
|
|
||||||
"link": "_cameraPlaneProj"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "envmapStrength",
|
"name": "envmapStrength",
|
||||||
"link": "_envmapStrength"
|
"link": "_envmapStrength"
|
||||||
@ -206,19 +172,8 @@
|
|||||||
{
|
{
|
||||||
"name": "pointPos",
|
"name": "pointPos",
|
||||||
"link": "_pointPosition",
|
"link": "_pointPosition",
|
||||||
"ifndef": ["_VRStereo"],
|
|
||||||
"ifdef": ["_SinglePoint"]
|
"ifdef": ["_SinglePoint"]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "pointPosLeft",
|
|
||||||
"link": "_pointPositionLeft",
|
|
||||||
"ifdef": ["_VRStereo", "_SinglePoint"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "pointPosRight",
|
|
||||||
"link": "_pointPositionRight",
|
|
||||||
"ifdef": ["_VRStereo", "_SinglePoint"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "pointCol",
|
"name": "pointCol",
|
||||||
"link": "_pointColor",
|
"link": "_pointColor",
|
||||||
|
|||||||
@ -97,31 +97,6 @@
|
|||||||
"link": "_cascadeData",
|
"link": "_cascadeData",
|
||||||
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
|
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "eyeLookRight",
|
|
||||||
"link": "_eyeLookRight",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invVPLeft",
|
|
||||||
"link": "_inverseViewProjectionMatrixLeft",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invVPRight",
|
|
||||||
"link": "_inverseViewProjectionMatrixRight",
|
|
||||||
"ifdef": ["_VRStereo"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "invVP",
|
|
||||||
"link": "_viewProjectionMatrix",
|
|
||||||
"ifdef": ["_SSRS"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "smSizeUniform",
|
|
||||||
"link": "_shadowMapSize",
|
|
||||||
"ifdef": ["_SMSizeUniform"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "lightPlane",
|
"name": "lightPlane",
|
||||||
"link": "_lightPlane",
|
"link": "_lightPlane",
|
||||||
@ -133,6 +108,8 @@
|
|||||||
"ifdef": ["_SSRS"]
|
"ifdef": ["_SSRS"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"name": "smSizeUniform",
|
||||||
|
"link": "_shadowMapSize",
|
||||||
"ifdef": ["_SMSizeUniform"]
|
"ifdef": ["_SMSizeUniform"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -143,19 +120,8 @@
|
|||||||
{
|
{
|
||||||
"name": "pointPos",
|
"name": "pointPos",
|
||||||
"link": "_pointPosition",
|
"link": "_pointPosition",
|
||||||
"ifndef": ["_VRStereo"],
|
|
||||||
"ifdef": ["_SinglePoint"]
|
"ifdef": ["_SinglePoint"]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "pointPosLeft",
|
|
||||||
"link": "_pointPositionLeft",
|
|
||||||
"ifdef": ["_VRStereo", "_SinglePoint"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "pointPosRight",
|
|
||||||
"link": "_pointPositionRight",
|
|
||||||
"ifdef": ["_VRStereo", "_SinglePoint"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "pointCol",
|
"name": "pointCol",
|
||||||
"link": "_pointColor",
|
"link": "_pointColor",
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
https://gpuopen.com/manuals/fidelityfx_sdk/license/
|
|
||||||
|
|
||||||
Copyright © 2024 Advanced Micro Devices, Inc.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and /or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@ -1,157 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
// AMD FidelityFX Super Resolution 1.0.2 - EASU (Edge Adaptive Spatial Upsampling)
|
|
||||||
|
|
||||||
#include "compiled.inc"
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
|
||||||
uniform vec2 screenSize;
|
|
||||||
|
|
||||||
in vec2 texCoord;
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
// Helper functions from AMD ffx_a.h
|
|
||||||
float APrxLoRcpF1(float a) {
|
|
||||||
return uintBitsToFloat(uint(0x7ef07ebb) - floatBitsToUint(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
float AMax3F1(float x, float y, float z) {
|
|
||||||
return max(x, max(y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
float AMin3F1(float x, float y, float z) {
|
|
||||||
return min(x, min(y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to use textureGather for efficiency when available
|
|
||||||
#if __VERSION__ >= 400
|
|
||||||
|
|
||||||
void FsrEasuTap(
|
|
||||||
inout vec3 aC,
|
|
||||||
inout float aW,
|
|
||||||
vec2 off,
|
|
||||||
vec2 dir,
|
|
||||||
vec2 len,
|
|
||||||
float lob,
|
|
||||||
float clp,
|
|
||||||
vec3 c
|
|
||||||
) {
|
|
||||||
vec2 v = off * dir;
|
|
||||||
float d2 = v.x + v.y;
|
|
||||||
d2 = clamp(d2 * APrxLoRcpF1(max(abs(v.x), abs(v.y))), 0.0, 1.0);
|
|
||||||
d2 = d2 * d2;
|
|
||||||
d2 = d2 * len.x + len.y;
|
|
||||||
float wB = 2.0 / 5.0 * d2 - 1.0;
|
|
||||||
float wA = lob * d2 - 1.0;
|
|
||||||
wB *= wB;
|
|
||||||
wA *= wA;
|
|
||||||
float w = 25.0 / 16.0 * wA * wB;
|
|
||||||
w = min(w, clp);
|
|
||||||
w = max(w, 0.0);
|
|
||||||
aC += c * w;
|
|
||||||
aW += w;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 FsrEasuF(vec2 ip) {
|
|
||||||
vec2 inputSize = textureSize(tex, 0);
|
|
||||||
vec2 inputRcp = 1.0 / inputSize;
|
|
||||||
|
|
||||||
// Position in input pixels
|
|
||||||
vec2 pp = ip * inputSize - 0.5;
|
|
||||||
vec2 fp = floor(pp);
|
|
||||||
pp -= fp;
|
|
||||||
|
|
||||||
// 12-tap kernel
|
|
||||||
// b c
|
|
||||||
// e f g h
|
|
||||||
// i j k l
|
|
||||||
// n o
|
|
||||||
ivec2 sp = ivec2(fp);
|
|
||||||
|
|
||||||
vec3 b = texelFetch(tex, sp + ivec2(0, -1), 0).rgb;
|
|
||||||
vec3 c = texelFetch(tex, sp + ivec2(1, -1), 0).rgb;
|
|
||||||
vec3 e = texelFetch(tex, sp + ivec2(-1, 0), 0).rgb;
|
|
||||||
vec3 f = texelFetch(tex, sp + ivec2(0, 0), 0).rgb;
|
|
||||||
vec3 g = texelFetch(tex, sp + ivec2(1, 0), 0).rgb;
|
|
||||||
vec3 h = texelFetch(tex, sp + ivec2(2, 0), 0).rgb;
|
|
||||||
vec3 i = texelFetch(tex, sp + ivec2(-1, 1), 0).rgb;
|
|
||||||
vec3 j = texelFetch(tex, sp + ivec2(0, 1), 0).rgb;
|
|
||||||
vec3 k = texelFetch(tex, sp + ivec2(1, 1), 0).rgb;
|
|
||||||
vec3 l = texelFetch(tex, sp + ivec2(2, 1), 0).rgb;
|
|
||||||
vec3 n = texelFetch(tex, sp + ivec2(0, 2), 0).rgb;
|
|
||||||
vec3 o = texelFetch(tex, sp + ivec2(1, 2), 0).rgb;
|
|
||||||
|
|
||||||
// Luma for edge detection (using green channel approximation)
|
|
||||||
float bL = b.g + 0.5 * (b.r + b.b);
|
|
||||||
float cL = c.g + 0.5 * (c.r + c.b);
|
|
||||||
float eL = e.g + 0.5 * (e.r + e.b);
|
|
||||||
float fL = f.g + 0.5 * (f.r + f.b);
|
|
||||||
float gL = g.g + 0.5 * (g.r + g.b);
|
|
||||||
float hL = h.g + 0.5 * (h.r + h.b);
|
|
||||||
float iL = i.g + 0.5 * (i.r + i.b);
|
|
||||||
float jL = j.g + 0.5 * (j.r + j.b);
|
|
||||||
float kL = k.g + 0.5 * (k.r + k.b);
|
|
||||||
float lL = l.g + 0.5 * (l.r + l.b);
|
|
||||||
float nL = n.g + 0.5 * (n.r + n.b);
|
|
||||||
float oL = o.g + 0.5 * (o.r + o.b);
|
|
||||||
|
|
||||||
// Gradient detection
|
|
||||||
float dirX = (cL - bL) + (gL - fL) + (kL - jL) + (oL - nL);
|
|
||||||
float dirY = (eL - iL) + (fL - jL) + (gL - kL) + (hL - lL);
|
|
||||||
|
|
||||||
// Normalize direction
|
|
||||||
float dirR = APrxLoRcpF1(max(abs(dirX), abs(dirY)));
|
|
||||||
dirX *= dirR;
|
|
||||||
dirY *= dirR;
|
|
||||||
|
|
||||||
// Calculate stretch based on edge direction
|
|
||||||
float len = length(vec2(dirX, dirY));
|
|
||||||
len = len * 0.5;
|
|
||||||
len *= len;
|
|
||||||
float stretch = (dirX * dirX + dirY * dirY) * APrxLoRcpF1(max(abs(dirX), abs(dirY)));
|
|
||||||
vec2 len2 = vec2(1.0 + (stretch - 1.0) * len, 1.0 - 0.5 * len);
|
|
||||||
float lob = 0.5 + (0.25 - 0.04 - 0.5) * len;
|
|
||||||
float clp = APrxLoRcpF1(lob);
|
|
||||||
|
|
||||||
// Accumulate samples
|
|
||||||
vec3 aC = vec3(0.0);
|
|
||||||
float aW = 0.0;
|
|
||||||
vec2 dir = vec2(dirX, dirY);
|
|
||||||
|
|
||||||
FsrEasuTap(aC, aW, vec2(0.0, -1.0) - pp, dir, len2, lob, clp, b);
|
|
||||||
FsrEasuTap(aC, aW, vec2(1.0, -1.0) - pp, dir, len2, lob, clp, c);
|
|
||||||
FsrEasuTap(aC, aW, vec2(-1.0, 0.0) - pp, dir, len2, lob, clp, e);
|
|
||||||
FsrEasuTap(aC, aW, vec2(0.0, 0.0) - pp, dir, len2, lob, clp, f);
|
|
||||||
FsrEasuTap(aC, aW, vec2(1.0, 0.0) - pp, dir, len2, lob, clp, g);
|
|
||||||
FsrEasuTap(aC, aW, vec2(2.0, 0.0) - pp, dir, len2, lob, clp, h);
|
|
||||||
FsrEasuTap(aC, aW, vec2(-1.0, 1.0) - pp, dir, len2, lob, clp, i);
|
|
||||||
FsrEasuTap(aC, aW, vec2(0.0, 1.0) - pp, dir, len2, lob, clp, j);
|
|
||||||
FsrEasuTap(aC, aW, vec2(1.0, 1.0) - pp, dir, len2, lob, clp, k);
|
|
||||||
FsrEasuTap(aC, aW, vec2(2.0, 1.0) - pp, dir, len2, lob, clp, l);
|
|
||||||
FsrEasuTap(aC, aW, vec2(0.0, 2.0) - pp, dir, len2, lob, clp, n);
|
|
||||||
FsrEasuTap(aC, aW, vec2(1.0, 2.0) - pp, dir, len2, lob, clp, o);
|
|
||||||
|
|
||||||
// Normalize
|
|
||||||
vec3 pix = aC / aW;
|
|
||||||
|
|
||||||
// Clamp to neighborhood min/max to prevent ringing
|
|
||||||
vec3 mn = min(min(min(f, g), j), k);
|
|
||||||
vec3 mx = max(max(max(f, g), j), k);
|
|
||||||
pix = clamp(pix, mn, mx);
|
|
||||||
|
|
||||||
return pix;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Fallback for older GLSL - simple bilinear
|
|
||||||
vec3 FsrEasuF(vec2 ip) {
|
|
||||||
return texture(tex, ip).rgb;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec3 col = FsrEasuF(texCoord);
|
|
||||||
fragColor = vec4(col, 1.0);
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"contexts": [
|
|
||||||
{
|
|
||||||
"name": "fsr1_easu_pass",
|
|
||||||
"depth_write": false,
|
|
||||||
"compare_mode": "always",
|
|
||||||
"cull_mode": "none",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"name": "screenSize",
|
|
||||||
"link": "_screenSize"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"texture_params": [],
|
|
||||||
"vertex_shader": "../include/pass.vert.glsl",
|
|
||||||
"fragment_shader": "fsr1_easu_pass.frag.glsl"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
https://gpuopen.com/manuals/fidelityfx_sdk/license/
|
|
||||||
|
|
||||||
Copyright © 2024 Advanced Micro Devices, Inc.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and /or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@ -1,116 +0,0 @@
|
|||||||
#version 450
|
|
||||||
|
|
||||||
// AMD FidelityFX Super Resolution 1.0.2 - RCAS (Robust Contrast Adaptive Sharpening)
|
|
||||||
|
|
||||||
#include "compiled.inc"
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
|
||||||
|
|
||||||
// Sharpness in "stops": 0.0 = maximum sharpness, higher = less sharp
|
|
||||||
// Converted to linear via exp2(-sharpness)
|
|
||||||
#ifdef _FSR1_Ultra_Quality
|
|
||||||
const float SHARPNESS_STOPS = 0.0;
|
|
||||||
#elif defined(_FSR1_Balanced)
|
|
||||||
const float SHARPNESS_STOPS = 1.0;
|
|
||||||
#elif defined(_FSR1_Performance)
|
|
||||||
const float SHARPNESS_STOPS = 2.0;
|
|
||||||
#elif defined(_FSR1_Custom)
|
|
||||||
uniform vec4 PPComp15;
|
|
||||||
#define SHARPNESS_STOPS (PPComp15.x * 2.0)
|
|
||||||
#else
|
|
||||||
const float SHARPNESS_STOPS = 0.5; // Quality (default)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// FSR RCAS limit - prevents unnatural sharpening artifacts
|
|
||||||
#define FSR_RCAS_LIMIT (0.25 - (1.0 / 16.0))
|
|
||||||
|
|
||||||
in vec2 texCoord;
|
|
||||||
out vec4 fragColor;
|
|
||||||
|
|
||||||
// AMD helper functions from ffx_a.h
|
|
||||||
float AMin3F1(float x, float y, float z) { return min(x, min(y, z)); }
|
|
||||||
float AMax3F1(float x, float y, float z) { return max(x, max(y, z)); }
|
|
||||||
|
|
||||||
// High precision reciprocal (required for limiters per AMD docs)
|
|
||||||
// Added epsilon to prevent division by zero in dark areas
|
|
||||||
float ARcpF1(float a) {
|
|
||||||
return 1.0 / max(a, 1e-8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Medium precision reciprocal approximation (from AMD ffx_a.h)
|
|
||||||
// Only used for noise detection and final resolve
|
|
||||||
float APrxMedRcpF1(float a) {
|
|
||||||
return uintBitsToFloat(uint(0x7ef19fff) - floatBitsToUint(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
// Get texture size and texel offset
|
|
||||||
vec2 texSize = vec2(textureSize(tex, 0));
|
|
||||||
vec2 texelSize = 1.0 / texSize;
|
|
||||||
|
|
||||||
// Algorithm uses minimal 3x3 pixel neighborhood
|
|
||||||
// b
|
|
||||||
// d e f
|
|
||||||
// h
|
|
||||||
// Clamp inputs to [0,1] - FSR expects sRGB normalized input
|
|
||||||
vec3 b = clamp(texture(tex, texCoord + vec2(0.0, -texelSize.y)).rgb, 0.0, 1.0);
|
|
||||||
vec3 d = clamp(texture(tex, texCoord + vec2(-texelSize.x, 0.0)).rgb, 0.0, 1.0);
|
|
||||||
vec4 ee = texture(tex, texCoord);
|
|
||||||
vec3 e = clamp(ee.rgb, 0.0, 1.0);
|
|
||||||
vec3 f = clamp(texture(tex, texCoord + vec2(texelSize.x, 0.0)).rgb, 0.0, 1.0);
|
|
||||||
vec3 h = clamp(texture(tex, texCoord + vec2(0.0, texelSize.y)).rgb, 0.0, 1.0);
|
|
||||||
|
|
||||||
// Luma times 2 (AMD's luma calculation: B*0.5 + R*0.5 + G)
|
|
||||||
float bL = b.b * 0.5 + (b.r * 0.5 + b.g);
|
|
||||||
float dL = d.b * 0.5 + (d.r * 0.5 + d.g);
|
|
||||||
float eL = e.b * 0.5 + (e.r * 0.5 + e.g);
|
|
||||||
float fL = f.b * 0.5 + (f.r * 0.5 + f.g);
|
|
||||||
float hL = h.b * 0.5 + (h.r * 0.5 + h.g);
|
|
||||||
|
|
||||||
// Noise detection (official AMD algorithm with safety for flat areas)
|
|
||||||
float nz = 0.25 * bL + 0.25 * dL + 0.25 * fL + 0.25 * hL - eL;
|
|
||||||
float range = AMax3F1(AMax3F1(bL, dL, eL), fL, hL) - AMin3F1(AMin3F1(bL, dL, eL), fL, hL);
|
|
||||||
// Use safe division instead of APrxMedRcpF1 for range to avoid NaN in flat areas
|
|
||||||
nz = clamp(abs(nz) / max(range, 1e-5), 0.0, 1.0);
|
|
||||||
nz = -0.5 * nz + 1.0;
|
|
||||||
|
|
||||||
// Min and max of ring (per channel)
|
|
||||||
float mn4R = min(AMin3F1(b.r, d.r, f.r), h.r);
|
|
||||||
float mn4G = min(AMin3F1(b.g, d.g, f.g), h.g);
|
|
||||||
float mn4B = min(AMin3F1(b.b, d.b, f.b), h.b);
|
|
||||||
float mx4R = max(AMax3F1(b.r, d.r, f.r), h.r);
|
|
||||||
float mx4G = max(AMax3F1(b.g, d.g, f.g), h.g);
|
|
||||||
float mx4B = max(AMax3F1(b.b, d.b, f.b), h.b);
|
|
||||||
|
|
||||||
// Immediate constants for peak range
|
|
||||||
vec2 peakC = vec2(1.0, -4.0);
|
|
||||||
|
|
||||||
// Limiters - these need HIGH PRECISION reciprocals (per AMD docs)
|
|
||||||
float hitMinR = min(mn4R, e.r) * ARcpF1(4.0 * mx4R);
|
|
||||||
float hitMinG = min(mn4G, e.g) * ARcpF1(4.0 * mx4G);
|
|
||||||
float hitMinB = min(mn4B, e.b) * ARcpF1(4.0 * mx4B);
|
|
||||||
float hitMaxR = (peakC.x - max(mx4R, e.r)) * ARcpF1(4.0 * mn4R + peakC.y);
|
|
||||||
float hitMaxG = (peakC.x - max(mx4G, e.g)) * ARcpF1(4.0 * mn4G + peakC.y);
|
|
||||||
float hitMaxB = (peakC.x - max(mx4B, e.b)) * ARcpF1(4.0 * mn4B + peakC.y);
|
|
||||||
float lobeR = max(-hitMinR, hitMaxR);
|
|
||||||
float lobeG = max(-hitMinG, hitMaxG);
|
|
||||||
float lobeB = max(-hitMinB, hitMaxB);
|
|
||||||
|
|
||||||
// Apply sharpness (convert from stops to linear)
|
|
||||||
float sharpness = exp2(-SHARPNESS_STOPS);
|
|
||||||
float lobe = max(-FSR_RCAS_LIMIT, min(AMax3F1(lobeR, lobeG, lobeB), 0.0)) * sharpness;
|
|
||||||
|
|
||||||
// Apply noise removal
|
|
||||||
lobe *= nz;
|
|
||||||
|
|
||||||
// Resolve using safe reciprocal to avoid any edge case issues
|
|
||||||
float denom = 4.0 * lobe + 1.0;
|
|
||||||
float rcpL = 1.0 / max(denom, 0.25); // denom should be in [0.25, 1.0] range
|
|
||||||
vec3 pix;
|
|
||||||
pix.r = (lobe * b.r + lobe * d.r + lobe * h.r + lobe * f.r + e.r) * rcpL;
|
|
||||||
pix.g = (lobe * b.g + lobe * d.g + lobe * h.g + lobe * f.g + e.g) * rcpL;
|
|
||||||
pix.b = (lobe * b.b + lobe * d.b + lobe * h.b + lobe * f.b + e.b) * rcpL;
|
|
||||||
|
|
||||||
// Ensure output is clamped to valid range
|
|
||||||
fragColor = vec4(clamp(pix, 0.0, 1.0), ee.a);
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"contexts": [
|
|
||||||
{
|
|
||||||
"name": "fsr1_rcas_pass",
|
|
||||||
"depth_write": false,
|
|
||||||
"compare_mode": "always",
|
|
||||||
"cull_mode": "none",
|
|
||||||
"links": [
|
|
||||||
{
|
|
||||||
"name": "screenSize",
|
|
||||||
"link": "_screenSize"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PPComp15",
|
|
||||||
"link": "_PPComp15",
|
|
||||||
"ifdef": ["_FSR1_Custom"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"texture_params": [],
|
|
||||||
"vertex_shader": "../include/pass.vert.glsl",
|
|
||||||
"fragment_shader": "fsr1_rcas_pass.frag.glsl"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -2,22 +2,13 @@
|
|||||||
|
|
||||||
#include "compiled.inc"
|
#include "compiled.inc"
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
|
||||||
uniform vec3 PPComp8;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
|
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
#ifdef _CPostprocess
|
|
||||||
fragColor.a = 0.01 * PPComp8.z;
|
|
||||||
#else
|
|
||||||
fragColor.a = 0.01 * autoExposureSpeed;
|
fragColor.a = 0.01 * autoExposureSpeed;
|
||||||
#endif
|
|
||||||
|
|
||||||
fragColor.rgb = textureLod(tex, vec2(0.5, 0.5), 0.0).rgb +
|
fragColor.rgb = textureLod(tex, vec2(0.5, 0.5), 0.0).rgb +
|
||||||
textureLod(tex, vec2(0.2, 0.2), 0.0).rgb +
|
textureLod(tex, vec2(0.2, 0.2), 0.0).rgb +
|
||||||
textureLod(tex, vec2(0.8, 0.2), 0.0).rgb +
|
textureLod(tex, vec2(0.8, 0.2), 0.0).rgb +
|
||||||
|
|||||||
@ -8,13 +8,7 @@
|
|||||||
"blend_source": "source_alpha",
|
"blend_source": "source_alpha",
|
||||||
"blend_destination": "inverse_source_alpha",
|
"blend_destination": "inverse_source_alpha",
|
||||||
"blend_operation": "add",
|
"blend_operation": "add",
|
||||||
"links": [
|
"links": [],
|
||||||
{
|
|
||||||
"name": "PPComp8",
|
|
||||||
"link": "_PPComp8",
|
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"texture_params": [],
|
"texture_params": [],
|
||||||
"vertex_shader": "../include/pass.vert.glsl",
|
"vertex_shader": "../include/pass.vert.glsl",
|
||||||
"fragment_shader": "histogram_pass.frag.glsl"
|
"fragment_shader": "histogram_pass.frag.glsl"
|
||||||
|
|||||||
@ -23,8 +23,9 @@ void main() {
|
|||||||
// fullscreen triangle: http://de.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau
|
// fullscreen triangle: http://de.slideshare.net/DevCentralAMD/vertex-shader-tricks-bill-bilodeau
|
||||||
// gl_Position = vec4((gl_VertexID % 2) * 4.0 - 1.0, (gl_VertexID / 2) * 4.0 - 1.0, 0.0, 1.0);
|
// gl_Position = vec4((gl_VertexID % 2) * 4.0 - 1.0, (gl_VertexID / 2) * 4.0 - 1.0, 0.0, 1.0);
|
||||||
|
|
||||||
// NDC (at the back of cube)
|
// For reverse-Z, the “far” plane lives at NDC z = 0
|
||||||
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
|
vec4 ndcFar = vec4(pos.x, pos.y, 0.0, 1.0);
|
||||||
|
vec4 v = invVP * ndcFar;
|
||||||
v = vec4(invVP * v);
|
v = vec4(invVP * v);
|
||||||
v.xyz /= v.w;
|
v.xyz /= v.w;
|
||||||
viewRay = v.xyz - eye;
|
viewRay = v.xyz - eye;
|
||||||
|
|||||||
@ -19,8 +19,9 @@ void main() {
|
|||||||
|
|
||||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||||
|
|
||||||
// NDC (at the back of cube)
|
// For reverse-Z, far plane sits at NDC z = 0
|
||||||
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
|
vec4 clip = vec4(pos.x, pos.y, 0.0, 1.0);
|
||||||
v = vec4(invP * v);
|
vec4 v = invP * clip;
|
||||||
|
// reconstruct a view‐space direction
|
||||||
viewRay = vec3(v.xy / v.z, 1.0);
|
viewRay = vec3(v.xy / v.z, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@ uniform sampler2D gbufferD;
|
|||||||
uniform sampler2D gbuffer0;
|
uniform sampler2D gbuffer0;
|
||||||
uniform sampler2D gbuffer1;
|
uniform sampler2D gbuffer1;
|
||||||
uniform mat4 invVP;
|
uniform mat4 invVP;
|
||||||
uniform mat4 invW;
|
|
||||||
uniform vec3 probep;
|
uniform vec3 probep;
|
||||||
uniform vec3 eye;
|
uniform vec3 eye;
|
||||||
|
|
||||||
@ -26,27 +25,19 @@ void main() {
|
|||||||
|
|
||||||
float roughness = g0.b;
|
float roughness = g0.b;
|
||||||
if (roughness > 0.95) {
|
if (roughness > 0.95) {
|
||||||
fragColor = vec4(0.0);
|
fragColor.rgb = vec3(0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||||
if (spec == 0.0) {
|
if (spec == 0.0) {
|
||||||
fragColor = vec4(0.0);
|
fragColor.rgb = vec3(0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||||
vec3 wp = getPos2(invVP, depth, texCoord);
|
vec3 wp = getPos2(invVP, depth, texCoord);
|
||||||
|
|
||||||
vec3 localPos = (invW * vec4(wp, 1.0)).xyz;
|
|
||||||
|
|
||||||
// return if surface is inside probe volume bounds
|
|
||||||
if (abs(localPos.x) > 1.0 || abs(localPos.y) > 1.0 || abs(localPos.z) > 1.0) {
|
|
||||||
fragColor = vec4(0.0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec2 enc = g0.rg;
|
vec2 enc = g0.rg;
|
||||||
vec3 n;
|
vec3 n;
|
||||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||||
@ -59,5 +50,5 @@ void main() {
|
|||||||
r.y = -r.y;
|
r.y = -r.y;
|
||||||
#endif
|
#endif
|
||||||
float intensity = clamp((1.0 - roughness) * dot(wp - probep, n), 0.0, 1.0);
|
float intensity = clamp((1.0 - roughness) * dot(wp - probep, n), 0.0, 1.0);
|
||||||
fragColor = vec4(texture(probeTex, r).rgb * intensity, 1.0);
|
fragColor.rgb = texture(probeTex, r).rgb * intensity;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,10 +20,6 @@
|
|||||||
"name": "invVP",
|
"name": "invVP",
|
||||||
"link": "_inverseViewProjectionMatrix"
|
"link": "_inverseViewProjectionMatrix"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "invW",
|
|
||||||
"link": "_inverseWorldMatrix"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "probep",
|
"name": "probep",
|
||||||
"link": "_probePosition"
|
"link": "_probePosition"
|
||||||
|
|||||||
@ -25,13 +25,13 @@ void main() {
|
|||||||
|
|
||||||
float roughness = g0.b;
|
float roughness = g0.b;
|
||||||
if (roughness > 0.95) {
|
if (roughness > 0.95) {
|
||||||
fragColor = vec4(0.0);
|
fragColor.rgb = vec3(0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||||
if (spec == 0.0) {
|
if (spec == 0.0) {
|
||||||
fragColor = vec4(0.0);
|
fragColor.rgb = vec3(0.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,5 +50,5 @@ void main() {
|
|||||||
n = normalize(n);
|
n = normalize(n);
|
||||||
|
|
||||||
float intensity = clamp((1.0 - roughness) * dot(n, proben), 0.0, 1.0);
|
float intensity = clamp((1.0 - roughness) * dot(n, proben), 0.0, 1.0);
|
||||||
fragColor = vec4(texture(probeTex, tc).rgb * intensity, 1.0);
|
fragColor.rgb = texture(probeTex, tc).rgb * intensity;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,56 +5,42 @@
|
|||||||
|
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
uniform sampler2D gbuffer0;
|
uniform sampler2D gbuffer0;
|
||||||
uniform sampler2D gbufferD;
|
|
||||||
|
|
||||||
uniform vec2 dirInv; // texStep
|
uniform vec2 dirInv; // texStep
|
||||||
|
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
out vec3 fragColor;
|
out float fragColor;
|
||||||
|
|
||||||
const int KERNEL_SIZE = 13;
|
const float blurWeights[5] = float[] (0.227027, 0.1945946, 0.1216216, 0.054054, 0.016216);
|
||||||
const float blurWeights[13] = float[](0.1, 0.09, 0.08, 0.07, 0.06, 0.05, 0.04, 0.03, 0.025, 0.02, 0.015, 0.01, 0.005);
|
// const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535);
|
||||||
|
const float discardThreshold = 0.95;
|
||||||
|
|
||||||
|
float doBlur(const float blurWeight, const int pos, const vec3 nor, const vec2 texCoord) {
|
||||||
|
const float posadd = pos + 0.5;
|
||||||
|
|
||||||
|
vec3 nor2 = getNor(textureLod(gbuffer0, texCoord + pos * dirInv, 0.0).rg);
|
||||||
|
float influenceFactor = step(discardThreshold, dot(nor2, nor));
|
||||||
|
float col = textureLod(tex, texCoord + posadd * dirInv, 0.0).r;
|
||||||
|
fragColor += col * blurWeight * influenceFactor;
|
||||||
|
float weight = blurWeight * influenceFactor;
|
||||||
|
|
||||||
|
nor2 = getNor(textureLod(gbuffer0, texCoord - pos * dirInv, 0.0).rg);
|
||||||
|
influenceFactor = step(discardThreshold, dot(nor2, nor));
|
||||||
|
col = textureLod(tex, texCoord - posadd * dirInv, 0.0).r;
|
||||||
|
fragColor += col * blurWeight * influenceFactor;
|
||||||
|
weight += blurWeight * influenceFactor;
|
||||||
|
|
||||||
|
return weight;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec3 centerNor = getNor(textureLod(gbuffer0, texCoord, 0.0).rg);
|
vec3 nor = getNor(textureLod(gbuffer0, texCoord, 0.0).rg);
|
||||||
float centerDepth = textureLod(gbufferD, texCoord, 0.0).r;
|
|
||||||
|
|
||||||
// skip sky pixels
|
fragColor = textureLod(tex, texCoord, 0.0).r * blurWeights[0];
|
||||||
if (centerDepth == 1.0) {
|
float weight = blurWeights[0];
|
||||||
fragColor = vec3(0.0);
|
for (int i = 1; i < 5; i++) {
|
||||||
return;
|
weight += doBlur(blurWeights[i], i, nor, texCoord);
|
||||||
}
|
}
|
||||||
|
|
||||||
fragColor = textureLod(tex, texCoord, 0.0).rgb * blurWeights[0];
|
fragColor = fragColor / weight;
|
||||||
float totalWeight = blurWeights[0];
|
|
||||||
|
|
||||||
for (int i = 1; i < KERNEL_SIZE; i++) {
|
|
||||||
vec2 offset = float(i) * dirInv;
|
|
||||||
|
|
||||||
vec2 uvPos = texCoord + offset;
|
|
||||||
vec3 norPos = getNor(textureLod(gbuffer0, uvPos, 0.0).rg);
|
|
||||||
float depthPos = textureLod(gbufferD, uvPos, 0.0).r;
|
|
||||||
|
|
||||||
float normalWeight = max(0.0, dot(norPos, centerNor));
|
|
||||||
normalWeight = pow(normalWeight, 8.0); // Softer normal falloff for better blending
|
|
||||||
float depthWeight = 1.0 - smoothstep(0.0, 0.02, abs(depthPos - centerDepth));
|
|
||||||
float w = blurWeights[i] * normalWeight * depthWeight;
|
|
||||||
|
|
||||||
fragColor += textureLod(tex, uvPos, 0.0).rgb * w;
|
|
||||||
totalWeight += w;
|
|
||||||
|
|
||||||
vec2 uvNeg = texCoord - offset;
|
|
||||||
vec3 norNeg = getNor(textureLod(gbuffer0, uvNeg, 0.0).rg);
|
|
||||||
float depthNeg = textureLod(gbufferD, uvNeg, 0.0).r;
|
|
||||||
|
|
||||||
normalWeight = max(0.0, dot(norNeg, centerNor));
|
|
||||||
normalWeight = pow(normalWeight, 8.0);
|
|
||||||
depthWeight = 1.0 - smoothstep(0.0, 0.02, abs(depthNeg - centerDepth));
|
|
||||||
w = blurWeights[i] * normalWeight * depthWeight;
|
|
||||||
|
|
||||||
fragColor += textureLod(tex, uvNeg, 0.0).rgb * w;
|
|
||||||
totalWeight += w;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragColor /= totalWeight;
|
|
||||||
}
|
}
|
||||||
@ -4,34 +4,37 @@
|
|||||||
#include "std/math.glsl"
|
#include "std/math.glsl"
|
||||||
#include "std/gbuffer.glsl"
|
#include "std/gbuffer.glsl"
|
||||||
|
|
||||||
uniform sampler2D gbuffer0;
|
|
||||||
uniform sampler2D gbuffer1;
|
|
||||||
uniform sampler2D gbufferD;
|
uniform sampler2D gbufferD;
|
||||||
#ifdef _EmissionShaded
|
uniform sampler2D gbuffer0; // Normal
|
||||||
uniform sampler2D gbufferEmission;
|
// #ifdef _RTGI
|
||||||
#endif
|
// uniform sampler2D gbuffer1; // Basecol
|
||||||
|
// #endif
|
||||||
uniform mat4 P;
|
uniform mat4 P;
|
||||||
uniform mat4 invP;
|
|
||||||
uniform mat3 V3;
|
uniform mat3 V3;
|
||||||
|
|
||||||
#ifdef _Sun
|
uniform vec2 cameraProj;
|
||||||
uniform vec3 sunDir;
|
|
||||||
uniform vec3 sunCol;
|
const float angleMix = 0.5f;
|
||||||
#endif
|
#ifdef _SSGICone9
|
||||||
|
const float strength = 2.0 * (1.0 / ssgiStrength);
|
||||||
#ifdef _CPostprocess
|
#else
|
||||||
uniform vec3 PPComp12;
|
const float strength = 2.0 * (1.0 / ssgiStrength) * 1.8;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
in vec3 viewRay;
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
out vec4 fragColor;
|
out float fragColor;
|
||||||
|
|
||||||
const float GOLDEN_ANGLE = 2.39996323;
|
vec3 hitCoord;
|
||||||
const int RAY_STEPS = 12;
|
vec2 coord;
|
||||||
|
float depth;
|
||||||
|
// #ifdef _RTGI
|
||||||
|
// vec3 col = vec3(0.0);
|
||||||
|
// #endif
|
||||||
|
vec3 vpos;
|
||||||
|
|
||||||
vec2 getProjectedCoord(const vec3 viewPos) {
|
vec2 getProjectedCoord(vec3 hitCoord) {
|
||||||
vec4 projectedCoord = P * vec4(viewPos, 1.0);
|
vec4 projectedCoord = P * vec4(hitCoord, 1.0);
|
||||||
projectedCoord.xy /= projectedCoord.w;
|
projectedCoord.xy /= projectedCoord.w;
|
||||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
||||||
#ifdef _InvY
|
#ifdef _InvY
|
||||||
@ -40,149 +43,65 @@ vec2 getProjectedCoord(const vec3 viewPos) {
|
|||||||
return projectedCoord.xy;
|
return projectedCoord.xy;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 cosineSampleHemisphere(vec3 n, vec2 rand) {
|
float getDeltaDepth(vec3 hitCoord) {
|
||||||
float phi = PI * 2.0 * rand.x;
|
coord = getProjectedCoord(hitCoord);
|
||||||
float cosTheta = sqrt(1.0 - rand.y);
|
depth = textureLod(gbufferD, coord, 0.0).r * 2.0 - 1.0;
|
||||||
float sinTheta = sqrt(rand.y);
|
vec3 p = getPosView(viewRay, depth, cameraProj);
|
||||||
|
return p.z - hitCoord.z;
|
||||||
vec3 h = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
|
|
||||||
|
|
||||||
vec3 tangent, 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) {
|
|
||||||
tangent = normalize(cross(n, vec3(0.0, 1.0, 0.0)));
|
|
||||||
} else {
|
|
||||||
tangent = normalize(cross(n, vec3(0.0, 0.0, 1.0)));
|
|
||||||
}
|
|
||||||
bitangent = cross(n, tangent);
|
|
||||||
|
|
||||||
return normalize(tangent * h.x + bitangent * h.y + n * h.z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 traceRay(vec3 origin, vec3 dir, float maxDist, float minDist) {
|
void rayCast(vec3 dir) {
|
||||||
float stepSize = maxDist / float(RAY_STEPS);
|
hitCoord = vpos;
|
||||||
vec3 pos = origin + dir * minDist;
|
dir *= ssgiRayStep * 2;
|
||||||
|
float dist = 0.15;
|
||||||
float prevDepthDiff = 0.0;
|
for (int i = 0; i < ssgiMaxSteps; i++) {
|
||||||
float hadValidPrev = 0.0;
|
hitCoord += dir;
|
||||||
|
float delta = getDeltaDepth(hitCoord);
|
||||||
for (int i = 1; i <= RAY_STEPS; i++) {
|
if (delta > 0.0 && delta < 0.2) {
|
||||||
pos += dir * stepSize;
|
dist = distance(vpos, hitCoord);
|
||||||
vec2 uv = getProjectedCoord(pos);
|
break;
|
||||||
|
}
|
||||||
vec2 sampleUV = clamp(uv, vec2(0.001), vec2(0.999));
|
}
|
||||||
|
fragColor += dist;
|
||||||
float sampleDepth = textureLod(gbufferD, sampleUV, 0.0).r * 2.0 - 1.0;
|
// #ifdef _RTGI
|
||||||
if (sampleDepth == 1.0) {
|
// col += textureLod(gbuffer1, coord, 0.0).rgb * ((ssgiRayStep * ssgiMaxSteps) - dist);
|
||||||
hadValidPrev = 0.0;
|
// #endif
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 sampleViewPos = getPosView2(invP, sampleDepth, sampleUV);
|
vec3 tangent(const vec3 n) {
|
||||||
float depthDiff = pos.z - sampleViewPos.z;
|
vec3 t1 = cross(n, vec3(0, 0, 1));
|
||||||
float rayDist = length(pos - origin);
|
vec3 t2 = cross(n, vec3(0, 1, 0));
|
||||||
float thickness = 0.15 + rayDist * 0.25;
|
if (length(t1) > length(t2)) return normalize(t1);
|
||||||
|
else return normalize(t2);
|
||||||
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);
|
|
||||||
|
|
||||||
return vec3(sampleUV, distWeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
prevDepthDiff = depthDiff;
|
|
||||||
hadValidPrev = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vec3(-1.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
fragColor = 0;
|
||||||
if (depth == 1.0) {
|
|
||||||
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||||
|
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||||
|
|
||||||
vec2 enc = g0.rg;
|
vec2 enc = g0.rg;
|
||||||
vec3 n;
|
vec3 n;
|
||||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||||
n = normalize(n);
|
n = normalize(V3 * n);
|
||||||
|
|
||||||
vec3 viewNormal = V3 * n;
|
vpos = getPosView(viewRay, d, cameraProj);
|
||||||
vec3 viewPos = getPosView2(invP, depth, texCoord);
|
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
rayCast(n);
|
||||||
float radius = PPComp12.y;
|
vec3 o1 = normalize(tangent(n));
|
||||||
float strength = PPComp12.x;
|
vec3 o2 = (cross(o1, n));
|
||||||
#else
|
vec3 c1 = 0.5f * (o1 + o2);
|
||||||
float radius = ssgiRadius;
|
vec3 c2 = 0.5f * (o1 - o2);
|
||||||
float strength = ssgiStrength;
|
rayCast(mix(n, o1, angleMix));
|
||||||
|
rayCast(mix(n, o2, angleMix));
|
||||||
|
rayCast(mix(n, -c1, angleMix));
|
||||||
|
rayCast(mix(n, -c2, angleMix));
|
||||||
|
|
||||||
|
#ifdef _SSGICone9
|
||||||
|
rayCast(mix(n, -o1, angleMix));
|
||||||
|
rayCast(mix(n, -o2, angleMix));
|
||||||
|
rayCast(mix(n, c1, angleMix));
|
||||||
|
rayCast(mix(n, c2, angleMix));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float noise = fract(52.9829189 * fract(0.06711056 * texCoord.x * 1000.0 + 0.00583715 * texCoord.y * 1000.0));
|
|
||||||
|
|
||||||
vec3 gi = vec3(0.0);
|
|
||||||
int validSamples = 0;
|
|
||||||
|
|
||||||
// min distance to avoid self shadowing artiffacts
|
|
||||||
float minDist = radius * 0.05;
|
|
||||||
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
|
|
||||||
vec3 rayDir = cosineSampleHemisphere(viewNormal, rand);
|
|
||||||
vec3 hitResult = traceRay(viewPos, rayDir, radius, minDist);
|
|
||||||
|
|
||||||
if (hitResult.x < 0.0) continue;
|
|
||||||
|
|
||||||
vec2 hitUV = hitResult.xy;
|
|
||||||
float distWeight = hitResult.z;
|
|
||||||
|
|
||||||
vec3 hitAlbedo = textureLod(gbuffer1, hitUV, 1.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;
|
|
||||||
#else
|
|
||||||
vec3 hitRadiance = hitAlbedo * 0.5;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _EmissionShaded
|
|
||||||
hitRadiance += textureLod(gbufferEmission, hitUV, 0.0).rgb;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gi += hitRadiance * distWeight;
|
|
||||||
validSamples++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validSamples > 0) {
|
|
||||||
gi /= float(validSamples);
|
|
||||||
}
|
|
||||||
|
|
||||||
gi *= strength;
|
|
||||||
|
|
||||||
#ifdef _EmissionShaded
|
|
||||||
gi += textureLod(gbufferEmission, texCoord, 0.0).rgb * 0.3;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fragColor = vec4(min(gi, vec3(2.0)), 1.0);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,32 +10,21 @@
|
|||||||
"name": "P",
|
"name": "P",
|
||||||
"link": "_projectionMatrix"
|
"link": "_projectionMatrix"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "invP",
|
|
||||||
"link": "_inverseProjectionMatrix"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "V3",
|
"name": "V3",
|
||||||
"link": "_viewMatrix3"
|
"link": "_viewMatrix3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sunDir",
|
"name": "invP",
|
||||||
"link": "_sunDirection",
|
"link": "_inverseProjectionMatrix"
|
||||||
"ifdef": ["_Sun"]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sunCol",
|
"name": "cameraProj",
|
||||||
"link": "_sunColor",
|
"link": "_cameraPlaneProj"
|
||||||
"ifdef": ["_Sun"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PPComp12",
|
|
||||||
"link": "_PPComp12",
|
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"texture_params": [],
|
"texture_params": [],
|
||||||
"vertex_shader": "../include/pass.vert.glsl",
|
"vertex_shader": "../include/pass_viewray2.vert.glsl",
|
||||||
"fragment_shader": "ssgi_pass.frag.glsl"
|
"fragment_shader": "ssgi_pass.frag.glsl"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,21 +1,35 @@
|
|||||||
|
// TODO: Integrate with Blender UI
|
||||||
|
// TODO: Option to disable cone tracing
|
||||||
|
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
#include "compiled.inc"
|
#include "compiled.inc"
|
||||||
#include "std/math.glsl"
|
#include "std/math.glsl"
|
||||||
#include "std/gbuffer.glsl"
|
#include "std/gbuffer.glsl"
|
||||||
|
|
||||||
uniform sampler2D tex;
|
// Environment map
|
||||||
uniform sampler2D gbufferD;
|
uniform float envmapStrength;
|
||||||
uniform sampler2D gbuffer0; // Normal, roughness
|
#ifdef _Irr
|
||||||
uniform sampler2D gbuffer1; // basecol, spec
|
uniform vec4 shirr[7];
|
||||||
uniform mat4 P;
|
uniform float ambientIntensity;
|
||||||
uniform mat3 V3;
|
#include "std/shirr.glsl"
|
||||||
uniform vec2 cameraProj;
|
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
|
||||||
uniform vec3 PPComp9;
|
|
||||||
uniform vec3 PPComp10;
|
|
||||||
#endif
|
#endif
|
||||||
|
#include "std/environment_sample.glsl"
|
||||||
|
|
||||||
|
uniform sampler2D tex; // Environment map
|
||||||
|
//uniform sampler2D depthtex; // Full Depth buffer
|
||||||
|
uniform sampler2D gbufferD; // Cheap Depth buffer
|
||||||
|
uniform sampler2D gbuffer0; // Normal, roughness
|
||||||
|
uniform sampler2D gbuffer1; // Base color, spec
|
||||||
|
uniform mat4 P; // Projection matrix
|
||||||
|
uniform mat3 V3; // View matrix
|
||||||
|
uniform vec2 cameraProj; // Camera projection params
|
||||||
|
uniform vec2 invScreenSize; // (1.0/width, 1.0/height)
|
||||||
|
|
||||||
|
const float ssrPrecision = 0.0; // 0.0 - 100.0 (user slider control)
|
||||||
|
//const float rayThickness = 0.1; // TODO: Adds some thickness to prevent gaps
|
||||||
|
uniform int ssrConetraceMode = 2; // 0 = no weighting, 1 = light, 2 = strong
|
||||||
|
const int ssrConetraceTaps = 18; // Number of taps (higher = more precision)
|
||||||
|
|
||||||
in vec3 viewRay;
|
in vec3 viewRay;
|
||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
@ -24,56 +38,136 @@ out vec4 fragColor;
|
|||||||
vec3 hitCoord;
|
vec3 hitCoord;
|
||||||
float depth;
|
float depth;
|
||||||
|
|
||||||
const int numBinarySearchSteps = 7;
|
const int baseBinarySearchSteps = 10; // Parameterize?
|
||||||
const int maxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);
|
const int baseMaxSteps = int(ceil(1.0 / ssrRayStep) * ssrSearchDist);
|
||||||
|
|
||||||
|
int dynamicBinarySearchSteps() {
|
||||||
|
return int(mix(7.0, 20.0, clamp(ssrPrecision / 100.0, 0.0, 1.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dynamicMaxSteps() {
|
||||||
|
return int(mix(float(baseMaxSteps), 300.0, clamp(ssrPrecision / 100.0, 0.0, 1.0)));
|
||||||
|
}
|
||||||
|
|
||||||
vec2 getProjectedCoord(const vec3 hit) {
|
vec2 getProjectedCoord(const vec3 hit) {
|
||||||
vec4 projectedCoord = P * vec4(hit, 1.0);
|
vec4 clip = P * vec4(hit, 1.0);
|
||||||
projectedCoord.xy /= projectedCoord.w;
|
vec2 uv = clip.xy / clip.w;
|
||||||
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
|
uv = uv * 0.5 + 0.5;
|
||||||
#ifdef _InvY
|
#ifdef _InvY
|
||||||
projectedCoord.y = 1.0 - projectedCoord.y;
|
uv.y = 1.0 - uv.y;
|
||||||
#endif
|
#endif
|
||||||
return projectedCoord.xy;
|
uv = clamp(uv, 0.0, 1.0);
|
||||||
|
uv += invScreenSize * 0.5; // half-pixel offset
|
||||||
|
return uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
float getDeltaDepth(const vec3 hit) {
|
float getDeltaDepth(const vec3 hit) {
|
||||||
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
|
vec2 screenUV = getProjectedCoord(hit);
|
||||||
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
|
float raw = textureLod(gbufferD, screenUV, 0.0).r;
|
||||||
return viewPos.z - hit.z;
|
float sampledDepth = raw * 2.0 - 1.0;
|
||||||
|
float linearSampledDepth = linearize(sampledDepth, cameraProj);
|
||||||
|
|
||||||
|
return linearSampledDepth - hit.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 binarySearch(vec3 dir) {
|
vec4 binarySearch(vec3 dir) {
|
||||||
float ddepth;
|
float ddepth;
|
||||||
for (int i = 0; i < numBinarySearchSteps; i++) {
|
for (int i = 0; i < dynamicBinarySearchSteps(); i++) {
|
||||||
dir *= 0.5;
|
dir *= 0.5;
|
||||||
hitCoord -= dir;
|
hitCoord -= dir;
|
||||||
ddepth = getDeltaDepth(hitCoord);
|
ddepth = getDeltaDepth(hitCoord);
|
||||||
if (ddepth < 0.0) hitCoord += dir;
|
if (ddepth < 0.0) hitCoord += dir;
|
||||||
}
|
}
|
||||||
// Ugly discard of hits too far away
|
|
||||||
#ifdef _CPostprocess
|
vec2 projectedCoord = getProjectedCoord(hitCoord);
|
||||||
if (abs(ddepth) > PPComp9.z / 500) return vec4(0.0);
|
float pixelSize = length(fwidth(projectedCoord)) * 0.5;
|
||||||
#else
|
float epsilon = max(pixelSize * 10.0, 0.01);
|
||||||
if (abs(ddepth) > ssrSearchDist / 500) return vec4(0.0);
|
|
||||||
#endif
|
if (abs(ddepth) > epsilon) return vec4(0.0);
|
||||||
return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
|
|
||||||
|
hitCoord.xy = clamp(projectedCoord, 0.0, 1.0);
|
||||||
|
|
||||||
|
return vec4(projectedCoord, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 rayCast(vec3 dir) {
|
vec4 rayCast(vec3 dir, float roughness) {
|
||||||
#ifdef _CPostprocess
|
vec3 stepDir = normalize(dir);
|
||||||
dir *= PPComp9.x;
|
|
||||||
#else
|
// Apply small jitter if high precision
|
||||||
dir *= ssrRayStep;
|
if (ssrPrecision > 80.0 && roughness > 0.05) {
|
||||||
#endif
|
stepDir = normalize(stepDir + vec3(rand2(texCoord), 0.0) * 0.01);
|
||||||
for (int i = 0; i < maxSteps; i++) {
|
|
||||||
hitCoord += dir;
|
|
||||||
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float distance = length(hitCoord - viewRay);
|
||||||
|
float stepDivisor = mix(100.0, 300.0, clamp(ssrPrecision / 100.0, 0.0, 1.0));
|
||||||
|
float stepSize = max(0.01, distance / stepDivisor);
|
||||||
|
float maxStepSize = 0.1;
|
||||||
|
|
||||||
|
for (int i = 0; i < dynamicMaxSteps(); i++) {
|
||||||
|
hitCoord += stepDir * stepSize;
|
||||||
|
|
||||||
|
vec2 projCoord = getProjectedCoord(hitCoord);
|
||||||
|
float sampledDepth = textureLod(gbufferD, projCoord, 0.0).r;
|
||||||
|
float depthTolerance = fwidth(sampledDepth) * 2.0; // Dynamic tolerance
|
||||||
|
|
||||||
|
if (getDeltaDepth(hitCoord) > depthTolerance) {
|
||||||
|
return binarySearch(stepDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
stepSize = min(stepSize * 1.1, maxStepSize);
|
||||||
|
}
|
||||||
|
|
||||||
return vec4(0.0);
|
return vec4(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec3 coneTraceApprox(vec3 reflDir, float roughness) {
|
||||||
|
vec3 result = vec3(0.0);
|
||||||
|
float totalWeight = 0.0;
|
||||||
|
|
||||||
|
float randAngle = hash12(texCoord) * 6.2831853;
|
||||||
|
mat2 rot = mat2(cos(randAngle), -sin(randAngle), sin(randAngle), cos(randAngle));
|
||||||
|
|
||||||
|
float coneSpread = roughness * 0.5; // widen based on roughness
|
||||||
|
|
||||||
|
for (int i = 0; i < ssrConetraceTaps; ++i) {
|
||||||
|
float angle = float(i) / float(ssrConetraceTaps) * 6.2831853;
|
||||||
|
vec2 offset = rot * vec2(cos(angle), sin(angle)) * coneSpread;
|
||||||
|
vec3 sampleDir = normalize(reflDir + vec3(offset, 0.0));
|
||||||
|
|
||||||
|
float weight = 1.0;
|
||||||
|
if (ssrConetraceMode == 1) {
|
||||||
|
weight = pow(max(dot(reflDir, sampleDir), 0.0), 2.0); // Light cosine lobe
|
||||||
|
}
|
||||||
|
else if (ssrConetraceMode == 2) {
|
||||||
|
weight = pow(max(dot(reflDir, sampleDir), 0.0), 8.0); // Strong GGX lobe
|
||||||
|
}
|
||||||
|
|
||||||
|
// Approximate sampling by using tex at reflection direction
|
||||||
|
vec2 envUV = envMapEquirect(sampleDir);
|
||||||
|
vec3 sampleColor = textureLod(tex, envUV, 0.0).rgb;
|
||||||
|
|
||||||
|
result += sampleColor * weight;
|
||||||
|
totalWeight += weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result / max(totalWeight, 0.0001);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 tangentSpaceGGX(vec3 N, float roughness) {
|
||||||
|
float a = roughness * roughness;
|
||||||
|
float phi = rand(texCoord) * 6.2831853;
|
||||||
|
float cosTheta = sqrt((1.0 - rand(texCoord)) / (1.0 + (a * a - 1.0) * rand(texCoord)));
|
||||||
|
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||||
|
|
||||||
|
vec3 T = normalize(cross(N, vec3(0.0, 1.0, 0.0)));
|
||||||
|
if (length(T) < 0.01) T = normalize(cross(N, vec3(1.0, 0.0, 0.0)));
|
||||||
|
vec3 B = cross(N, T);
|
||||||
|
|
||||||
|
return normalize(T * cos(phi) * sinTheta + B * sin(phi) * sinTheta + N * cosTheta);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
|
||||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||||
float roughness = unpackFloat(g0.b).y;
|
float roughness = unpackFloat(g0.b).y;
|
||||||
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
if (roughness == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
||||||
@ -81,41 +175,77 @@ void main() {
|
|||||||
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
|
||||||
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
||||||
|
|
||||||
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
// sample raw depth, bail if empty
|
||||||
if (d == 1.0) { fragColor.rgb = vec3(0.0); return; }
|
float dRaw = textureLod(gbufferD, texCoord, 0.0).r;
|
||||||
|
if (dRaw == 0.0) { fragColor.rgb = vec3(0.0); return; }
|
||||||
vec2 enc = g0.rg;
|
// convert to NDC z before reconstructing
|
||||||
vec3 n;
|
float d = dRaw * 2.0 - 1.0;
|
||||||
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 = decode_oct(g0.rg);
|
||||||
vec3 viewNormal = V3 * n;
|
vec3 viewNormal = V3 * n;
|
||||||
|
viewNormal = normalize(mix(viewNormal, normalize(-viewRay), 0.05)); // slightly bias the normal toward the view direction at glancing angles
|
||||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||||
vec3 reflected = reflect(viewPos, viewNormal);
|
vec3 viewDir = normalize(-viewPos);
|
||||||
|
vec3 idealReflection = reflect(normalize(viewPos), viewNormal);
|
||||||
hitCoord = viewPos;
|
hitCoord = viewPos;
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
// Apply GGX importance sampling in tangent space
|
||||||
vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0;
|
vec3 jitteredDir = tangentSpaceGGX(viewNormal, roughness);
|
||||||
#else
|
|
||||||
vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// * max(ssrMinRayStep, -viewPos.z)
|
// Blend based on roughness (0 = perfect mirror, 1 = fully scattered)
|
||||||
vec4 coords = rayCast(dir);
|
vec3 dir = normalize(mix(idealReflection, jitteredDir, roughness));
|
||||||
|
|
||||||
|
vec4 coords = rayCast(dir, roughness);
|
||||||
|
|
||||||
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||||
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||||
|
|
||||||
float reflectivity = 1.0 - roughness;
|
float reflectivity = 1.0 - roughness;
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
#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;
|
// Postprocess mode intensity calculation...
|
||||||
#else
|
#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 intensity = 0.0;
|
||||||
|
|
||||||
|
if (coords.w > 0.0) {
|
||||||
|
// Ray hit in screen-space
|
||||||
|
intensity = pow(reflectivity, ssrFalloffExp) * screenEdgeFactor *
|
||||||
|
clamp(-idealReflection.z, 0.0, 1.0) *
|
||||||
|
clamp((ssrSearchDist - length(viewPos - hitCoord)) * (1.0 / ssrSearchDist), 0.0, 1.0);
|
||||||
|
}
|
||||||
|
else if (roughness < 0.7) {
|
||||||
|
// Ray miss, roughness low enough: do cone trace approximation
|
||||||
|
vec3 coneColor = coneTraceApprox(idealReflection, roughness);
|
||||||
|
vec3 envCol = sampleSpecularEnvironment(idealReflection, roughness);
|
||||||
|
|
||||||
|
coneColor = clamp(coneColor, 0.0, 1.0);
|
||||||
|
envCol = clamp(envCol, 0.0, 1.0);
|
||||||
|
|
||||||
|
vec3 finalColor = mix(envCol, mix(envCol, coneColor, intensity), coords.w);
|
||||||
|
fragColor.rgb = finalColor * 0.5; // match previous intensity scaling
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Ray miss, roughness too high: fallback to environment map
|
||||||
|
vec3 fallbackEnvColor = sampleSpecularEnvironment(reflect(viewDir, n), roughness);
|
||||||
|
fragColor.rgb = fallbackEnvColor;
|
||||||
|
return;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb; // SSR reflection
|
||||||
|
vec3 envCol = textureLod(tex, texCoord, 0.0).rgb; // Background environment
|
||||||
|
|
||||||
intensity = clamp(intensity, 0.0, 1.0);
|
intensity = clamp(intensity, 0.0, 1.0);
|
||||||
vec3 reflCol = textureLod(tex, coords.xy, 0.0).rgb;
|
|
||||||
reflCol = clamp(reflCol, 0.0, 1.0);
|
reflCol = clamp(reflCol, 0.0, 1.0);
|
||||||
fragColor.rgb = reflCol * intensity * 0.5;
|
envCol = clamp(envCol, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Roughness-based fade (smoothstep)
|
||||||
|
float roughFade = smoothstep(0.2, 0.7, roughness);
|
||||||
|
float ssrVisibility = coords.w * (1.0 - roughFade);
|
||||||
|
|
||||||
|
// Blend SSR
|
||||||
|
vec3 finalColor = mix(envCol, reflCol, ssrVisibility);
|
||||||
|
|
||||||
|
fragColor.rgb = finalColor;
|
||||||
}
|
}
|
||||||
@ -4,6 +4,7 @@
|
|||||||
"name": "ssr_pass",
|
"name": "ssr_pass",
|
||||||
"depth_write": false,
|
"depth_write": false,
|
||||||
"compare_mode": "always",
|
"compare_mode": "always",
|
||||||
|
"blend_mode": "replace",
|
||||||
"cull_mode": "none",
|
"cull_mode": "none",
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
@ -23,14 +24,12 @@
|
|||||||
"link": "_cameraPlaneProj"
|
"link": "_cameraPlaneProj"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "PPComp9",
|
"name": "coneTraceMode",
|
||||||
"link": "_PPComp9",
|
"link": "_coneTraceMode"
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "PPComp10",
|
"name": "coneTraceTapCount",
|
||||||
"link": "_PPComp10",
|
"link": "_coneTraceTapCount"
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"texture_params": [],
|
"texture_params": [],
|
||||||
|
|||||||
@ -64,26 +64,20 @@ vec4 rayCast(vec3 dir) {
|
|||||||
ddepth = getDeltaDepth(hitCoord);
|
ddepth = getDeltaDepth(hitCoord);
|
||||||
if (ddepth > 0.0) return binarySearch(dir);
|
if (ddepth > 0.0) return binarySearch(dir);
|
||||||
}
|
}
|
||||||
return vec4(texCoord, 0.0, 0.0);
|
return vec4(texCoord, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0);
|
|
||||||
float ior = 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) {
|
|
||||||
vec3 background = textureLod(tex1, texCoord, 0.0).rgb;
|
|
||||||
fragColor.rgb = sceneSample.rgb + background * (1.0 - sceneSample.a);
|
|
||||||
fragColor.a = 1.0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
||||||
float roughness = g0.z;
|
float roughness = g0.z;
|
||||||
|
vec4 gr = textureLod(gbuffer_refraction, texCoord, 0.0);
|
||||||
|
float ior = gr.x;
|
||||||
|
float opac = gr.y;
|
||||||
|
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
|
||||||
|
if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) {
|
||||||
|
fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb;
|
||||||
|
return;
|
||||||
|
}
|
||||||
vec2 enc = g0.rg;
|
vec2 enc = g0.rg;
|
||||||
vec3 n;
|
vec3 n;
|
||||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||||
@ -92,32 +86,21 @@ void main() {
|
|||||||
|
|
||||||
vec3 viewNormal = V3 * n;
|
vec3 viewNormal = V3 * n;
|
||||||
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
vec3 viewPos = getPosView(viewRay, d, cameraProj);
|
||||||
vec3 incident = normalize(viewPos);
|
vec3 refracted = refract(normalize(viewPos), viewNormal, 1.0 / ior);
|
||||||
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.a = 1.0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hitCoord = viewPos;
|
hitCoord = viewPos;
|
||||||
|
|
||||||
vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0;
|
vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0;
|
||||||
vec4 coords = rayCast(dir);
|
vec4 coords = rayCast(dir);
|
||||||
|
vec2 deltaCoords = abs(vec2(0.5, 0.5) - coords.xy);
|
||||||
vec2 screenEdge = smoothstep(0.0, 0.1, coords.xy) * smoothstep(0.0, 0.1, 1.0 - coords.xy);
|
float screenEdgeFactor = clamp(1.0 - (deltaCoords.x + deltaCoords.y), 0.0, 1.0);
|
||||||
float screenEdgeFactor = screenEdge.x * screenEdge.y;
|
|
||||||
float refractivity = 1.0 - roughness;
|
float refractivity = 1.0 - roughness;
|
||||||
|
float intensity = pow(refractivity, ss_refractionFalloffExp) * screenEdgeFactor * \
|
||||||
float intensity = pow(refractivity, ss_refractionFalloffExp) * screenEdgeFactor * coords.w;
|
clamp(-refracted.z, 0.0, 1.0) * clamp((length(viewPos - hitCoord)), 0.0, 1.0) * coords.w;
|
||||||
intensity = clamp(intensity, 0.0, 1.0);
|
intensity = clamp(intensity, 0.0, 1.0);
|
||||||
|
|
||||||
vec3 refractedBackground = textureLod(tex1, coords.xy, 0.0).rgb;
|
vec3 refractionCol = textureLod(tex1, coords.xy, 0.0).rgb;
|
||||||
vec3 straightBackground = textureLod(tex1, texCoord, 0.0).rgb;
|
refractionCol *= intensity;
|
||||||
|
vec3 color = textureLod(tex, texCoord.xy, 0.0).rgb;
|
||||||
|
|
||||||
vec3 behindColor = mix(straightBackground, refractedBackground, intensity);
|
fragColor.rgb = mix(refractionCol, color, opac);
|
||||||
|
|
||||||
fragColor.rgb = sceneSample.rgb + behindColor * (1.0 - sceneSample.a);
|
|
||||||
fragColor.a = 1.0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,6 @@
|
|||||||
"depth_write": false,
|
"depth_write": false,
|
||||||
"compare_mode": "always",
|
"compare_mode": "always",
|
||||||
"cull_mode": "none",
|
"cull_mode": "none",
|
||||||
"blend_source": "blend_one",
|
|
||||||
"blend_destination": "blend_zero",
|
|
||||||
"blend_operation": "add",
|
|
||||||
"links": [
|
"links": [
|
||||||
{
|
{
|
||||||
"name": "P",
|
"name": "P",
|
||||||
|
|||||||
@ -36,7 +36,6 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
#include "compiled.inc"
|
#include "compiled.inc"
|
||||||
#include "std/gbuffer.glsl"
|
|
||||||
|
|
||||||
uniform sampler2D gbufferD;
|
uniform sampler2D gbufferD;
|
||||||
uniform sampler2D gbuffer0;
|
uniform sampler2D gbuffer0;
|
||||||
@ -48,92 +47,69 @@ uniform vec2 cameraProj;
|
|||||||
in vec2 texCoord;
|
in vec2 texCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
const vec3 SKIN_SSS_RADIUS = vec3(4.8, 2.4, 1.5);
|
const float SSSS_FOVY = 108.0;
|
||||||
const float SSS_DISTANCE_SCALE = 0.001;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Separable SSS Reflectance
|
||||||
|
// const float sssWidth = 0.005;
|
||||||
vec4 SSSSBlur() {
|
vec4 SSSSBlur() {
|
||||||
const int SSSS_N_SAMPLES = 15;
|
// Quality = 0
|
||||||
|
const int SSSS_N_SAMPLES = 11;
|
||||||
vec4 kernel[SSSS_N_SAMPLES];
|
vec4 kernel[SSSS_N_SAMPLES];
|
||||||
|
kernel[0] = vec4(0.560479, 0.669086, 0.784728, 0);
|
||||||
kernel[0] = vec4(0.233, 0.455, 0.649, 0.0); // Center sample
|
kernel[1] = vec4(0.00471691, 0.000184771, 5.07566e-005, -2);
|
||||||
kernel[1] = vec4(0.100, 0.336, 0.344, 0.37); // +0.37mm
|
kernel[2] = vec4(0.0192831, 0.00282018, 0.00084214, -1.28);
|
||||||
kernel[2] = vec4(0.118, 0.198, 0.0, 0.97); // +0.97mm
|
kernel[3] = vec4(0.03639, 0.0130999, 0.00643685, -0.72);
|
||||||
kernel[3] = vec4(0.113, 0.007, 0.007, 1.93); // +1.93mm
|
kernel[4] = vec4(0.0821904, 0.0358608, 0.0209261, -0.32);
|
||||||
kernel[4] = vec4(0.358, 0.004, 0.0, 3.87); // +3.87mm
|
kernel[5] = vec4(0.0771802, 0.113491, 0.0793803, -0.08);
|
||||||
kernel[5] = vec4(0.078, 0.0, 0.0, 6.53); // +6.53mm (red only)
|
kernel[6] = vec4(0.0771802, 0.113491, 0.0793803, 0.08);
|
||||||
kernel[6] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
|
kernel[7] = vec4(0.0821904, 0.0358608, 0.0209261, 0.32);
|
||||||
kernel[7] = vec4(0.0, 0.0, 0.0, 0.0); // Unused
|
kernel[8] = vec4(0.03639, 0.0130999, 0.00643685, 0.72);
|
||||||
kernel[8] = vec4(0.100, 0.336, 0.344, -0.37); // -0.37mm
|
kernel[9] = vec4(0.0192831, 0.00282018, 0.00084214, 1.28);
|
||||||
kernel[9] = vec4(0.118, 0.198, 0.0, -0.97); // -0.97mm
|
kernel[10] = vec4(0.00471691, 0.000184771, 5.07565e-005, 2);
|
||||||
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);
|
vec4 colorM = textureLod(tex, texCoord, 0.0);
|
||||||
|
|
||||||
|
// Fetch linear depth of current pixel
|
||||||
float depth = textureLod(gbufferD, texCoord, 0.0).r;
|
float depth = textureLod(gbufferD, texCoord, 0.0).r;
|
||||||
float depthM = cameraProj.y / (depth - cameraProj.x);
|
float depthM = cameraProj.y / (depth - cameraProj.x);
|
||||||
|
|
||||||
float distanceScale = 1.0 / max(depthM, 0.1);
|
// Calculate the sssWidth scale (1.0 for a unit plane sitting on the projection window)
|
||||||
|
float distanceToProjectionWindow = 1.0 / tan(0.5 * radians(SSSS_FOVY));
|
||||||
|
float scale = distanceToProjectionWindow / depthM;
|
||||||
|
|
||||||
vec2 finalStep = sssWidth * distanceScale * dir * SSS_DISTANCE_SCALE;
|
// Calculate the final step to fetch the surrounding pixels
|
||||||
|
vec2 finalStep = sssWidth * scale * dir;
|
||||||
|
finalStep *= 1.0;//SSSS_STREGTH_SOURCE; // Modulate it using the alpha channel.
|
||||||
|
finalStep *= 1.0 / 3.0; // Divide by 3 as the kernels range from -3 to 3.
|
||||||
|
finalStep *= 0.05; //
|
||||||
|
|
||||||
|
// Accumulate the center sample:
|
||||||
|
vec4 colorBlurred = colorM;
|
||||||
|
colorBlurred.rgb *= kernel[0].rgb;
|
||||||
|
|
||||||
vec3 jitterSeed = vec3(texCoord.xy * 1000.0, fract(cameraProj.x * 0.0001));
|
// Accumulate the other samples
|
||||||
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;
|
|
||||||
|
|
||||||
for (int i = 1; i < SSSS_N_SAMPLES; i++) {
|
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;
|
// Fetch color and depth for current sample
|
||||||
vec2 offset = texCoord + (kernel[i].a + sampleJitter) * finalStep;
|
vec2 offset = texCoord + kernel[i].a * finalStep;
|
||||||
vec4 color = textureLod(tex, offset, 0.0);
|
vec4 color = textureLod(tex, offset, 0.0);
|
||||||
const float DEPTH_THRESHOLD = 0.05;
|
//#if SSSS_FOLLOW_SURFACE == 1
|
||||||
float sampleDepth = textureLod(gbufferD, offset, 0.0).r;
|
// If the difference in depth is huge, we lerp color back to "colorM":
|
||||||
float sampleDepthM = cameraProj.y / (sampleDepth - cameraProj.x);
|
//float depth = textureLod(tex, offset, 0.0).r;
|
||||||
|
//float s = clamp(300.0f * distanceToProjectionWindow * sssWidth * abs(depthM - depth),0.0,1.0);
|
||||||
float depthDiff = abs(depthM - sampleDepthM);
|
//color.rgb = mix(color.rgb, colorM.rgb, s);
|
||||||
float depthWeight = exp(-depthDiff * 10.0);
|
//#endif
|
||||||
|
// Accumulate
|
||||||
if (depthDiff > DEPTH_THRESHOLD) {
|
colorBlurred.rgb += kernel[i].rgb * color.rgb;
|
||||||
color.rgb = mix(colorM.rgb, color.rgb, depthWeight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
colorBlurred += color.rgb * kernel[i].rgb;
|
return colorBlurred;
|
||||||
weightSum += kernel[i].rgb;
|
|
||||||
}
|
|
||||||
vec3 normalizedColor = 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0);
|
if (textureLod(gbuffer0, texCoord, 0.0).a == 8192.0) {
|
||||||
float metallic;
|
fragColor = clamp(SSSSBlur(), 0.0, 1.0);
|
||||||
uint matid;
|
}
|
||||||
unpackFloatInt16(g0.a, metallic, matid);
|
else {
|
||||||
|
|
||||||
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)));
|
|
||||||
} else {
|
|
||||||
fragColor = textureLod(tex, texCoord, 0.0);
|
fragColor = textureLod(tex, texCoord, 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
#ifndef _AABB_GLSL
|
|
||||||
#define _AABB_GLSL
|
|
||||||
|
|
||||||
bool IntersectAABB(vec3[2] a, vec3[2] b) {
|
|
||||||
const float EPSILON = 0.001; // Small tolerance to prevent false negatives
|
|
||||||
if (abs(a[0].x - b[0].x) > (a[1].x + b[1].x + EPSILON)) return false;
|
|
||||||
if (abs(a[0].y - b[0].y) > (a[1].y + b[1].y + EPSILON)) return false;
|
|
||||||
if (abs(a[0].z - b[0].z) > (a[1].z + b[1].z + EPSILON)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AABBfromMinMax(inout vec3[2] aabb, vec3 _min, vec3 _max)
|
|
||||||
{
|
|
||||||
aabb[0] = (_min + _max) * 0.5f;
|
|
||||||
aabb[1] = abs(_max - aabb[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,8 +1,10 @@
|
|||||||
#ifndef _BRDF_GLSL_
|
#ifndef _BRDF_GLSL_
|
||||||
#define _BRDF_GLSL_
|
#define _BRDF_GLSL_
|
||||||
|
|
||||||
// http://xlgames-inc.github.io/posts/improvedibl/
|
// Constants
|
||||||
// http://blog.selfshadow.com/publications/s2013-shading-course/
|
//const float PI = 3.1415926535;
|
||||||
|
|
||||||
|
// Fresnel-Schlick with optimized exponential approximation
|
||||||
vec3 f_schlick(const vec3 f0, const float vh) {
|
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((-5.55473 * vh - 6.98316) * vh);
|
||||||
}
|
}
|
||||||
@ -11,83 +13,11 @@ float v_smithschlick(const float nl, const float nv, const float a) {
|
|||||||
return 1.0 / ((nl * (1.0 - a) + a) * (nv * (1.0 - a) + a));
|
return 1.0 / ((nl * (1.0 - a) + a) * (nv * (1.0 - a) + a));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Uncorrelated masking/shadowing (info below) function
|
|
||||||
//Because it is uncorrelated, G1(NdotL, a) gives us shadowing, and G1(NdotV, a) gives us masking function.
|
|
||||||
//Approximation from: https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
|
|
||||||
float g1_approx(const float NdotX, const float alpha)
|
|
||||||
{
|
|
||||||
return (2.0 * NdotX) * (1.0 / (NdotX * (2.0 - alpha) + alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Uncorrelated masking-shadowing function
|
|
||||||
//Approximation from: https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
|
|
||||||
float g2_approx(const float NdotL, const float NdotV, const float alpha)
|
|
||||||
{
|
|
||||||
vec2 helper = (2.0 * vec2(NdotL, NdotV)) * (1.0 / (vec2(NdotL, NdotV) * (2.0 - alpha) + alpha));
|
|
||||||
return max(helper.x * helper.y, 0.0); //This can go negative, let's fix that
|
|
||||||
}
|
|
||||||
|
|
||||||
float d_ggx(const float nh, const float a) {
|
float d_ggx(const float nh, const float a) {
|
||||||
float a2 = a * a;
|
float a2 = a * a;
|
||||||
float denom = nh * nh * (a2 - 1.0) + 1.0;
|
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 */);
|
denom = max(denom * denom, 2e-6);
|
||||||
return a2 * (1.0 / 3.1415926535) / denom;
|
return a2 / (PI * denom);
|
||||||
}
|
|
||||||
|
|
||||||
vec3 specularBRDF(const vec3 f0, const float roughness, const float nl, const float nh, const float nv, const float vh) {
|
|
||||||
float a = roughness * roughness;
|
|
||||||
vec3 result = d_ggx(nh, a) * g2_approx(nl, nv, a) * f_schlick(f0, vh) / max(4.0 * nv, 1e-5); //NdotL cancels out later
|
|
||||||
return min(result, vec3(200.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// John Hable - Optimizing GGX Shaders
|
|
||||||
// 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);
|
|
||||||
// F
|
|
||||||
const float F_a = 1.0;
|
|
||||||
float F_b = pow(1.0 - dotLH, 5.0);
|
|
||||||
// V
|
|
||||||
float vis;
|
|
||||||
float k = alpha / 2.0;
|
|
||||||
float k2 = k * k;
|
|
||||||
float invK2 = 1.0 - k2;
|
|
||||||
vis = 1.0 / (dotLH * dotLH * invK2 + k2);
|
|
||||||
vec2 FV_helper = vec2((F_a - F_b) * vis, F_b * vis);
|
|
||||||
|
|
||||||
vec3 FV = f0 * FV_helper.x + FV_helper.y;
|
|
||||||
vec3 specular = clamp(dotNL, 0.0, 1.0) * D * FV;
|
|
||||||
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 * nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
|
|
||||||
return mix(baseColor, vec3(0.0), metalness);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 surfaceF0(const vec3 baseColor, const float metalness) {
|
|
||||||
return mix(vec3(0.04), baseColor, metalness);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float getMipFromRoughness(const float roughness, const float numMipmaps) {
|
float getMipFromRoughness(const float roughness, const float numMipmaps) {
|
||||||
@ -95,47 +25,64 @@ float getMipFromRoughness(const float roughness, const float numMipmaps) {
|
|||||||
return roughness * numMipmaps;
|
return roughness * numMipmaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
float wardSpecular(vec3 N, vec3 H, float dotNL, float dotNV, float dotNH, vec3 fiberDirection, float shinyParallel, float shinyPerpendicular) {
|
vec3 specularBRDF(vec3 N, vec3 V, vec3 L, vec3 F0, float roughness)
|
||||||
if(dotNL < 0.0 || dotNV < 0.0) {
|
{
|
||||||
return 0.0;
|
vec3 H = normalize(V + L);
|
||||||
}
|
|
||||||
// fiberDirection - parse from rotation
|
|
||||||
// shinyParallel - roughness
|
|
||||||
// shinyPerpendicular - anisotropy
|
|
||||||
|
|
||||||
vec3 fiberParallel = normalize(fiberDirection);
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
vec3 fiberPerpendicular = normalize(cross(N, fiberDirection));
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
float dotXH = dot(fiberParallel, H);
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
float dotYH = dot(fiberPerpendicular, H);
|
float VdotH = max(dot(V, H), 0.0);
|
||||||
const float PI = 3.1415926535;
|
|
||||||
float coeff = sqrt(dotNL/dotNV) / (4.0 * PI * shinyParallel * shinyPerpendicular);
|
float alpha = roughness * roughness;
|
||||||
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);
|
float D = d_ggx(NdotH, alpha);
|
||||||
|
float k = alpha / 2.0;
|
||||||
|
float G_V = NdotV / (NdotV * (1.0 - k) + k + 1e-5);
|
||||||
|
float G_L = NdotL / (NdotL * (1.0 - k) + k + 1e-5);
|
||||||
|
float G = G_V * G_L;
|
||||||
|
|
||||||
|
vec3 F = f_schlick(F0, VdotH);
|
||||||
|
|
||||||
|
return F * D * G / max(4.0 * NdotL * NdotV, 1e-5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
|
vec3 burleyDiffuseBRDF(vec3 N, vec3 V, vec3 L, vec3 albedo, float roughness)
|
||||||
// vec3 EnvBRDFApprox(vec3 SpecularColor, float Roughness, float NoV) {
|
{
|
||||||
// const vec4 c0 = { -1, -0.0275, -0.572, 0.022 };
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
// const vec4 c1 = { 1, 0.0425, 1.04, -0.04 };
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
// vec4 r = Roughness * c0 + c1;
|
float LdotH = max(dot(L, normalize(L + V)), 0.0);
|
||||||
// float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
|
||||||
// vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
|
float FD90 = 0.5 + 2.0 * LdotH * LdotH * roughness;
|
||||||
// return SpecularColor * AB.x + AB.y;
|
float FL = pow(1.0 - NdotL, 5.0);
|
||||||
// }
|
float FV = pow(1.0 - NdotV, 5.0);
|
||||||
// float EnvBRDFApproxNonmetal(float Roughness, float NoV) {
|
|
||||||
// // Same as EnvBRDFApprox( 0.04, Roughness, NoV )
|
float diffuse = (1.0 + (FD90 - 1.0) * FL) * (1.0 + (FD90 - 1.0) * FV);
|
||||||
// const vec2 c0 = { -1, -0.0275 };
|
return albedo * (1.0 / PI) * diffuse * NdotL;
|
||||||
// const vec2 c1 = { 1, 0.0425 };
|
}
|
||||||
// vec2 r = Roughness * c0 + c1;
|
|
||||||
// return min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
|
// Energy-conserving material albedo (fades out for metals)
|
||||||
// }
|
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
|
||||||
float D_Approx(const float Roughness, const float RoL) {
|
return baseColor * (1.0 - metalness);
|
||||||
float a = Roughness * Roughness;
|
}
|
||||||
float a2 = a * a;
|
|
||||||
float rcp_a2 = 1.0 / a2;//rcp(a2);
|
// Metal-aware F0 blending
|
||||||
// 0.5 / ln(2), 0.275 / ln(2)
|
vec3 surfaceF0(vec3 baseColor, float metalness) {
|
||||||
float c = 0.72134752 * rcp_a2 + 0.39674113;
|
return mix(vec3(0.04), baseColor, metalness);
|
||||||
return rcp_a2 * exp2( c * RoL - c );
|
}
|
||||||
|
|
||||||
|
// LUT-based approximation of IBL BRDF (Unreal-style)
|
||||||
|
vec2 EnvBRDFApprox(float Roughness, float NoV) {
|
||||||
|
const vec4 c0 = vec4(-1, -0.0275, -0.572, 0.022);
|
||||||
|
const vec4 c1 = vec4(1, 0.0425, 1.04, -0.04);
|
||||||
|
vec4 r = Roughness * c0 + c1;
|
||||||
|
float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
|
||||||
|
return vec2(-1.04, 1.04) * a004 + r.zw;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 IBLSpecularApprox(vec3 specColor, float roughness, float NoV) {
|
||||||
|
vec2 brdf = EnvBRDFApprox(roughness, NoV);
|
||||||
|
return specColor * brdf.x + brdf.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -22,7 +22,7 @@ THE SOFTWARE.
|
|||||||
#ifndef _CONETRACE_GLSL_
|
#ifndef _CONETRACE_GLSL_
|
||||||
#define _CONETRACE_GLSL_
|
#define _CONETRACE_GLSL_
|
||||||
|
|
||||||
#include "std/constants.glsl"
|
#include "std/voxels_constants.glsl"
|
||||||
|
|
||||||
// References
|
// References
|
||||||
// https://github.com/Friduric/voxel-cone-tracing
|
// https://github.com/Friduric/voxel-cone-tracing
|
||||||
@ -92,14 +92,14 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
|||||||
float dist = voxelSize0;
|
float dist = voxelSize0;
|
||||||
float step_dist = dist;
|
float step_dist = dist;
|
||||||
vec3 samplePos;
|
vec3 samplePos;
|
||||||
vec3 start_pos = origin + n * voxelSize0;
|
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||||
int clipmap_index0 = 0;
|
int clipmap_index0 = 0;
|
||||||
|
|
||||||
vec3 aniso_direction = -dir;
|
vec3 aniso_direction = -dir;
|
||||||
vec3 face_offset = vec3(
|
vec3 face_offset = vec3(
|
||||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
aniso_direction.x > 0.0 ? 0 : 1,
|
||||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
aniso_direction.y > 0.0 ? 2 : 3,
|
||||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
aniso_direction.z > 0.0 ? 4 : 5
|
||||||
) / (6 + DIFFUSE_CONE_COUNT);
|
) / (6 + DIFFUSE_CONE_COUNT);
|
||||||
vec3 direction_weight = abs(dir);
|
vec3 direction_weight = abs(dir);
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
|||||||
|
|
||||||
if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
|
||||||
vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
|
vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
|
||||||
mipSample = mix(mipSample, mipSampleNext, clipmap_blend);
|
mipSample = mix(mipSample, mipSampleNext, smoothstep(0.0, 1.0, clipmap_blend));
|
||||||
}
|
}
|
||||||
|
|
||||||
sampleCol += (1.0 - sampleCol.a) * mipSample;
|
sampleCol += (1.0 - sampleCol.a) * mipSample;
|
||||||
@ -148,9 +148,8 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
|
|||||||
vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
|
vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||||
float sum = 0.0;
|
float sum = 0.0;
|
||||||
vec4 amount = vec4(0.0);
|
vec4 amount = vec4(0.0);
|
||||||
mat3 TBN = makeTangentBasis(normal);
|
|
||||||
for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) {
|
for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) {
|
||||||
vec3 coneDir = TBN * DIFFUSE_CONE_DIRECTIONS[i];
|
vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i];
|
||||||
const float cosTheta = dot(normal, coneDir);
|
const float cosTheta = dot(normal, coneDir);
|
||||||
if (cosTheta <= 0)
|
if (cosTheta <= 0)
|
||||||
continue;
|
continue;
|
||||||
@ -167,7 +166,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels,
|
|||||||
}
|
}
|
||||||
|
|
||||||
vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
||||||
vec3 specularDir = reflect(normalize(-viewDir), normal);
|
vec3 specularDir = reflect(-viewDir, normal);
|
||||||
vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep;
|
vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep;
|
||||||
vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps);
|
vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps);
|
||||||
|
|
||||||
@ -177,9 +176,9 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels,
|
|||||||
return amount * voxelgiOcc;
|
return amount * voxelgiOcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) {
|
vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
|
||||||
const float transmittance = 1.0 - opacity;
|
const float transmittance = 1.0;
|
||||||
vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior);
|
vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior);
|
||||||
vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
|
vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
|
||||||
vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps);
|
vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps);
|
||||||
|
|
||||||
@ -197,14 +196,14 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
|
|||||||
float dist = voxelSize0;
|
float dist = voxelSize0;
|
||||||
float step_dist = dist;
|
float step_dist = dist;
|
||||||
vec3 samplePos;
|
vec3 samplePos;
|
||||||
vec3 start_pos = origin + n * voxelSize0;
|
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||||
int clipmap_index0 = 0;
|
int clipmap_index0 = 0;
|
||||||
|
|
||||||
vec3 aniso_direction = -dir;
|
vec3 aniso_direction = -dir;
|
||||||
vec3 face_offset = vec3(
|
vec3 face_offset = vec3(
|
||||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
aniso_direction.x > 0.0 ? 0 : 1,
|
||||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
aniso_direction.y > 0.0 ? 2 : 3,
|
||||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
aniso_direction.z > 0.0 ? 4 : 5
|
||||||
) / (6 + DIFFUSE_CONE_COUNT);
|
) / (6 + DIFFUSE_CONE_COUNT);
|
||||||
vec3 direction_weight = abs(dir);
|
vec3 direction_weight = abs(dir);
|
||||||
|
|
||||||
@ -260,6 +259,7 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
|
float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
|
||||||
float sampleCol = 0.0;
|
float sampleCol = 0.0;
|
||||||
@ -267,14 +267,14 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
|||||||
float dist = voxelSize0;
|
float dist = voxelSize0;
|
||||||
float step_dist = dist;
|
float step_dist = dist;
|
||||||
vec3 samplePos;
|
vec3 samplePos;
|
||||||
vec3 start_pos = origin + n * voxelSize0;
|
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset;
|
||||||
int clipmap_index0 = 0;
|
int clipmap_index0 = 0;
|
||||||
|
|
||||||
vec3 aniso_direction = -dir;
|
vec3 aniso_direction = -dir;
|
||||||
vec3 face_offset = vec3(
|
vec3 face_offset = vec3(
|
||||||
aniso_direction.x > 0.0 ? 0.0 : 1.0,
|
aniso_direction.x > 0.0 ? 0 : 1,
|
||||||
aniso_direction.y > 0.0 ? 2.0 : 3.0,
|
aniso_direction.y > 0.0 ? 2 : 3,
|
||||||
aniso_direction.z > 0.0 ? 4.0 : 5.0
|
aniso_direction.z > 0.0 ? 4 : 5
|
||||||
) / (6 + DIFFUSE_CONE_COUNT);
|
) / (6 + DIFFUSE_CONE_COUNT);
|
||||||
vec3 direction_weight = abs(dir);
|
vec3 direction_weight = abs(dir);
|
||||||
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
float coneCoefficient = 2.0 * tan(aperture * 0.5);
|
||||||
@ -287,7 +287,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
|
|||||||
float clipmap_blend = fract(lod);
|
float clipmap_blend = fract(lod);
|
||||||
vec3 p0 = start_pos + dir * dist;
|
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);
|
samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x);
|
||||||
samplePos = samplePos * 0.5 + 0.5;
|
samplePos = samplePos * 0.5 + 0.5;
|
||||||
|
|
||||||
if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) {
|
if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) {
|
||||||
@ -328,9 +328,9 @@ 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) {
|
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) {
|
||||||
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
|
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.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, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps);
|
||||||
amount = clamp(amount, 0.0, 1.0);
|
amount = clamp(amount, 0.0, 1.0);
|
||||||
return amount * voxelgiOcc;
|
return amount * voxelgiOcc;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2024 Turánszki János
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const int DIFFUSE_CONE_COUNT = 16;
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
// TO DO - Disabled momentarily instead of changing formulas
|
|
||||||
const float off_BayerMatrix8[8][8] =
|
|
||||||
{
|
|
||||||
{ 1.0 / 65.0, 49.0 / 65.0, 13.0 / 65.0, 61.0 / 65.0, 4.0 / 65.0, 52.0 / 65.0, 16.0 / 65.0, 64.0 / 65.0 },
|
|
||||||
{ 33.0 / 65.0, 17.0 / 65.0, 45.0 / 65.0, 29.0 / 65.0, 36.0 / 65.0, 20.0 / 65.0, 48.0 / 65.0, 32.0 / 65.0 },
|
|
||||||
{ 9.0 / 65.0, 57.0 / 65.0, 5.0 / 65.0, 53.0 / 65.0, 12.0 / 65.0, 60.0 / 65.0, 8.0 / 65.0, 56.0 / 65.0 },
|
|
||||||
{ 41.0 / 65.0, 25.0 / 65.0, 37.0 / 65.0, 21.0 / 65.0, 44.0 / 65.0, 28.0 / 65.0, 40.0 / 65.0, 24.0 / 65.0 },
|
|
||||||
{ 3.0 / 65.0, 51.0 / 65.0, 15.0 / 65.0, 63.0 / 65.0, 2.0 / 65.0, 50.0 / 65.0, 14.0 / 65.0, 62.0 / 65.0 },
|
|
||||||
{ 35.0 / 65.0, 19.0 / 65.0, 47.0 / 65.0, 31.0 / 65.0, 34.0 / 65.0, 18.0 / 65.0, 46.0 / 65.0, 30.0 / 65.0 },
|
|
||||||
{ 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 },
|
|
||||||
{ 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 }
|
|
||||||
};
|
|
||||||
const float BayerMatrix8[8][8] =
|
|
||||||
{
|
|
||||||
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
|
|
||||||
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
|
|
||||||
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
|
|
||||||
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
|
|
||||||
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
|
|
||||||
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
|
|
||||||
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
|
|
||||||
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
@ -8,10 +8,10 @@
|
|||||||
// const float compoDOFLength = 160.0; // Focal length in mm 18-200
|
// const float compoDOFLength = 160.0; // Focal length in mm 18-200
|
||||||
// const float compoDOFFstop = 128.0; // F-stop value
|
// const float compoDOFFstop = 128.0; // F-stop value
|
||||||
|
|
||||||
const int samples = 8; // Samples on the first ring
|
const int samples = 6; // Samples on the first ring
|
||||||
const int rings = 6; // Ring count
|
const int rings = 6; // Ring count
|
||||||
const vec2 focus = vec2(0.5, 0.5);
|
const vec2 focus = vec2(0.5, 0.5);
|
||||||
const float coc = 0.03; // Circle of confusion size in mm (35mm film = 0.03mm)
|
const float coc = 0.11; // Circle of confusion size in mm (35mm film = 0.03mm)
|
||||||
const float maxblur = 1.0;
|
const float maxblur = 1.0;
|
||||||
const float threshold = 0.5; // Highlight threshold
|
const float threshold = 0.5; // Highlight threshold
|
||||||
const float gain = 2.0; // Highlight gain
|
const float gain = 2.0; // Highlight gain
|
||||||
@ -55,26 +55,21 @@ vec3 dof(
|
|||||||
float f = DOFLength; // Focal length in mm
|
float f = DOFLength; // Focal length in mm
|
||||||
float d = fDepth * 1000.0; // Focal plane in mm
|
float d = fDepth * 1000.0; // Focal plane in mm
|
||||||
float o = depth * 1000.0; // Depth in mm
|
float o = depth * 1000.0; // Depth in mm
|
||||||
float a = (o > f) ? (o * f) / (o - f) : 0.0;
|
float a = (o * f) / (o - f);
|
||||||
float b = (d > f) ? (d * f) / (d - f) : 0.0;
|
float b = (d * f) / (d - f);
|
||||||
float sensorSize = max(DOFFStop, 10.0);
|
float c = (d - f) / (d * DOFFStop * coc);
|
||||||
float c = (d - f) / (d * sensorSize * coc);
|
|
||||||
|
|
||||||
float blur = abs(a - b) * c;
|
float blur = abs(a - b) * c;
|
||||||
blur = clamp(blur, 0.0, 1.0);
|
blur = clamp(blur, 0.0, 1.0);
|
||||||
|
|
||||||
vec2 noise = rand2(texCoord) * namount * blur;
|
vec2 noise = rand2(texCoord) * namount * blur;
|
||||||
float w = (texStep.x) * blur * maxblur + noise.x;
|
float w = (texStep.x) * blur * maxblur + noise.x;
|
||||||
float h = (texStep.y) * blur * maxblur + noise.y;
|
float h = (texStep.y) * blur * maxblur + noise.y;
|
||||||
vec3 sharpCol = textureLod(tex, texCoord, 0.0).rgb;
|
vec3 col = vec3(0.0);
|
||||||
vec3 col = sharpCol;
|
if (blur < 0.05) {
|
||||||
float blurThreshold = 0.02;
|
col = textureLod(tex, texCoord, 0.0).rgb;
|
||||||
float blurRange = 0.06;
|
}
|
||||||
|
else {
|
||||||
if (blur > blurThreshold) {
|
col = textureLod(tex, texCoord, 0.0).rgb;
|
||||||
float blurAmount = smoothstep(blurThreshold, blurThreshold + blurRange, blur);
|
|
||||||
|
|
||||||
vec3 blurredCol = sharpCol;
|
|
||||||
float s = 1.0;
|
float s = 1.0;
|
||||||
int ringsamples;
|
int ringsamples;
|
||||||
|
|
||||||
@ -86,12 +81,11 @@ vec3 dof(
|
|||||||
float ph = (sin(float(j) * step) * float(i));
|
float ph = (sin(float(j) * step) * float(i));
|
||||||
float p = 1.0;
|
float p = 1.0;
|
||||||
// if (pentagon) p = penta(vec2(pw, ph));
|
// if (pentagon) p = penta(vec2(pw, ph));
|
||||||
blurredCol += color(texCoord + vec2(pw * w, ph * h), blur, tex, texStep) * mix(1.0, (float(i)) / (float(rings)), bias) * p;
|
col += color(texCoord + vec2(pw * w, ph * h), blur, tex, texStep) * mix(1.0, (float(i)) / (float(rings)), bias) * p;
|
||||||
s += 1.0 * mix(1.0, (float(i)) / (float(rings)), bias) * p;
|
s += 1.0 * mix(1.0, (float(i)) / (float(rings)), bias) * p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blurredCol /= s;
|
col /= s;
|
||||||
col = mix(sharpCol, blurredCol, blurAmount);
|
|
||||||
}
|
}
|
||||||
return col;
|
return col;
|
||||||
}
|
}
|
||||||
|
|||||||
28
leenkx/Shaders/std/environment_sample.glsl
Normal file
28
leenkx/Shaders/std/environment_sample.glsl
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _ENVIRONMENT_SAMPLE_GLSL_
|
||||||
|
#define _ENVIRONMENT_SAMPLE_GLSL_
|
||||||
|
|
||||||
|
// Sample diffuse ambient environment lighting (irradiance)
|
||||||
|
vec3 sampleDiffuseEnvironment(vec3 normal) {
|
||||||
|
#ifdef _Irr
|
||||||
|
vec3 envl = shIrradiance(normal, shirr);
|
||||||
|
|
||||||
|
#ifdef _EnvTex
|
||||||
|
envl /= PI;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return envl;
|
||||||
|
#else
|
||||||
|
return vec3(0.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample specular environment reflection (skybox or cubemap)
|
||||||
|
vec3 sampleSpecularEnvironment(vec3 viewDir, float roughness) {
|
||||||
|
#ifdef _EnvTex
|
||||||
|
return textureLod(texEnvironment, viewDir, roughness * 8.0).rgb;
|
||||||
|
#else
|
||||||
|
return vec3(0.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -1,11 +1,12 @@
|
|||||||
#ifndef _GBUFFER_GLSL_
|
#ifndef _GBUFFER_GLSL_
|
||||||
#define _GBUFFER_GLSL_
|
#define _GBUFFER_GLSL_
|
||||||
|
#include "std/math.glsl"
|
||||||
|
|
||||||
vec2 octahedronWrap(vec2 v) {
|
vec2 octahedronWrap(const vec2 v) {
|
||||||
return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
|
return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 getNor(vec2 enc) {
|
vec3 getNor(const vec2 enc) {
|
||||||
vec3 n;
|
vec3 n;
|
||||||
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
n.z = 1.0 - abs(enc.x) - abs(enc.y);
|
||||||
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
|
||||||
@ -13,33 +14,27 @@ vec3 getNor(vec2 enc) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 getPosView(vec3 viewRay, float depth, vec2 cameraProj) {
|
vec3 getPosView(const vec3 viewRay, float depth, vec2 cameraProj) {
|
||||||
float linearDepth = cameraProj.y / (cameraProj.x - depth);
|
return viewRay * linearize(depth, cameraProj);
|
||||||
//float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
|
||||||
return viewRay * linearDepth;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 getPos(vec3 eye, vec3 eyeLook, vec3 viewRay, float depth, vec2 cameraProj) {
|
vec3 getPos(const vec3 eye, mat3 invV, const vec3 viewRay, float depth, vec2 cameraProj) {
|
||||||
// eyeLook, viewRay should be normalized
|
vec3 pVS = viewRay * linearize(depth, cameraProj);
|
||||||
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
return eye + invV * pVS; // invV == inverse of view-rotation
|
||||||
float viewZDist = dot(eyeLook, viewRay);
|
|
||||||
vec3 wposition = eye + viewRay * (linearDepth / viewZDist);
|
|
||||||
return wposition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 getPosNoEye(vec3 eyeLook, vec3 viewRay, float depth, vec2 cameraProj) {
|
vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
|
||||||
// eyeLook, viewRay should be normalized
|
float linearDepth = linearize(depth, cameraProj);
|
||||||
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
|
|
||||||
float viewZDist = dot(eyeLook, viewRay);
|
float viewZDist = dot(eyeLook, viewRay);
|
||||||
vec3 wposition = viewRay * (linearDepth / viewZDist);
|
vec3 wposition = viewRay * (linearDepth / viewZDist);
|
||||||
return wposition;
|
return wposition;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HLSL) || defined(METAL)
|
#if defined(HLSL) || defined(METAL)
|
||||||
vec3 getPos2(mat4 invVP, float depth, vec2 coord) {
|
vec3 getPos2(const mat4 invVP, const float depth, vec2 coord) {
|
||||||
coord.y = 1.0 - coord.y;
|
coord.y = 1.0 - coord.y;
|
||||||
#else
|
#else
|
||||||
vec3 getPos2(mat4 invVP, float depth, vec2 coord) {
|
vec3 getPos2(const mat4 invVP, const float depth, const vec2 coord) {
|
||||||
#endif
|
#endif
|
||||||
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||||
pos = invVP * pos;
|
pos = invVP * pos;
|
||||||
@ -47,48 +42,51 @@ vec3 getPos2(mat4 invVP, float depth, vec2 coord) {
|
|||||||
return pos.xyz;
|
return pos.xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HLSL) || defined(METAL)
|
//#if defined(HLSL) || defined(METAL)
|
||||||
|
//vec3 getPosView2(const mat4 invP, const float depth, vec2 coord) {
|
||||||
|
// coord.y = 1.0 - coord.y;
|
||||||
|
//#else
|
||||||
vec3 getPosView2(mat4 invP, float depth, vec2 coord) {
|
vec3 getPosView2(mat4 invP, float depth, vec2 coord) {
|
||||||
coord.y = 1.0 - coord.y;
|
vec4 clip = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||||
#else
|
vec4 view = invP * clip;
|
||||||
vec3 getPosView2(mat4 invP, float depth, vec2 coord) {
|
return view.xyz / view.w;
|
||||||
#endif
|
//#endif
|
||||||
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
||||||
pos = invP * pos;
|
pos = invP * pos;
|
||||||
pos.xyz /= pos.w;
|
pos.xyz /= pos.w;
|
||||||
return pos.xyz;
|
return pos.xyz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reconstruct view-space position from inverse View×Proj
|
||||||
|
vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, const vec2 coord) {
|
||||||
|
vec2 uv = coord;
|
||||||
#if defined(HLSL) || defined(METAL)
|
#if defined(HLSL) || defined(METAL)
|
||||||
vec3 getPos2NoEye(vec3 eye, mat4 invVP, float depth, vec2 coord) {
|
uv.y = 1.0 - uv.y;
|
||||||
coord.y = 1.0 - coord.y;
|
|
||||||
#else
|
|
||||||
vec3 getPos2NoEye(vec3 eye, mat4 invVP, float depth, vec2 coord) {
|
|
||||||
#endif
|
#endif
|
||||||
vec4 pos = vec4(coord * 2.0 - 1.0, depth, 1.0);
|
vec4 clip = vec4(uv * 2.0 - 1.0, depth, 1.0);
|
||||||
pos = invVP * pos;
|
vec4 world = invVP * clip;
|
||||||
pos.xyz /= pos.w;
|
world.xyz /= world.w;
|
||||||
return pos.xyz - eye;
|
return world.xyz - eye;
|
||||||
}
|
}
|
||||||
|
|
||||||
float packFloat(float f1, float f2) {
|
// Updated to support separate roughness/metalness storage
|
||||||
|
float packFloat(const float f1, const float f2) {
|
||||||
return floor(f1 * 100.0) + min(f2, 1.0 - 1.0 / 100.0);
|
return floor(f1 * 100.0) + min(f2, 1.0 - 1.0 / 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 unpackFloat(float f) {
|
vec2 unpackFloat(const float f) {
|
||||||
return vec2(floor(f) / 100.0, fract(f));
|
return vec2(floor(f) / 100.0, fract(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
float packFloat2(float f1, float f2) {
|
float packFloat2(const float f1, const float f2) {
|
||||||
// Higher f1 = less precise f2
|
|
||||||
return floor(f1 * 255.0) + min(f2, 1.0 - 1.0 / 100.0);
|
return floor(f1 * 255.0) + min(f2, 1.0 - 1.0 / 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 unpackFloat2(float f) {
|
vec2 unpackFloat2(const float f) {
|
||||||
return vec2(floor(f) / 255.0, fract(f));
|
return vec2(floor(f) / 255.0, fract(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 encodeRGBM(vec3 rgb) {
|
vec4 encodeRGBM(const vec3 rgb) {
|
||||||
const float maxRange = 6.0;
|
const float maxRange = 6.0;
|
||||||
float maxRGB = max(rgb.x, max(rgb.g, rgb.b));
|
float maxRGB = max(rgb.x, max(rgb.g, rgb.b));
|
||||||
float m = maxRGB / maxRange;
|
float m = maxRGB / maxRange;
|
||||||
@ -96,28 +94,25 @@ vec4 encodeRGBM(vec3 rgb) {
|
|||||||
return vec4(rgb / (m * maxRange), m);
|
return vec4(rgb / (m * maxRange), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 decodeRGBM(vec4 rgbm) {
|
vec3 decodeRGBM(const vec4 rgbm) {
|
||||||
const float maxRange = 6.0;
|
const float maxRange = 6.0;
|
||||||
return rgbm.rgb * rgbm.a * maxRange;
|
return rgbm.rgb * rgbm.a * maxRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 signNotZero(vec2 v)
|
vec2 signNotZero(vec2 v) {
|
||||||
{
|
|
||||||
return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
|
return vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 encode_oct(vec3 v)
|
vec2 encode_oct(vec3 v) {
|
||||||
{
|
|
||||||
// Project the sphere onto the octahedron, and then onto the xy plane
|
|
||||||
vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
|
vec2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z)));
|
||||||
// Reflect the folds of the lower hemisphere over the diagonals
|
|
||||||
return (v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p;
|
return (v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 decode_oct(vec2 e)
|
vec3 decode_oct(vec2 e) {
|
||||||
{
|
|
||||||
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
|
vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
|
||||||
if (v.z < 0) v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy);
|
if (v.z < 0.0) {
|
||||||
|
v.xy = (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
|
||||||
|
}
|
||||||
return normalize(v);
|
return normalize(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,10 +142,7 @@ vec3 decNor(uint val) {
|
|||||||
return normal;
|
return normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
float packFloatInt16(const float f, const uint i) {
|
||||||
Packs a float in [0, 1] and an integer in [0..15] into a single 16 bit float value.
|
|
||||||
**/
|
|
||||||
float packFloatInt16(float f, uint i) {
|
|
||||||
const uint numBitFloat = 12;
|
const uint numBitFloat = 12;
|
||||||
const float maxValFloat = float((1 << numBitFloat) - 1);
|
const float maxValFloat = float((1 << numBitFloat) - 1);
|
||||||
|
|
||||||
@ -160,12 +152,11 @@ float packFloatInt16(float f, uint i) {
|
|||||||
return float(bitsInt | bitsFloat);
|
return float(bitsInt | bitsFloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unpackFloatInt16(float val, out float f, out uint i) {
|
void unpackFloatInt16(const float val, out float f, out uint i) {
|
||||||
const uint numBitFloat = 12;
|
const uint numBitFloat = 12;
|
||||||
const float maxValFloat = float((1 << numBitFloat) - 1);
|
const float maxValFloat = float((1 << numBitFloat) - 1);
|
||||||
|
|
||||||
const uint bitsValue = uint(val);
|
const uint bitsValue = uint(val);
|
||||||
|
|
||||||
i = bitsValue >> numBitFloat;
|
i = bitsValue >> numBitFloat;
|
||||||
f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat;
|
f = (bitsValue & ~(0xF << numBitFloat)) / maxValFloat;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
#include "std/conetrace.glsl"
|
#include "std/conetrace.glsl"
|
||||||
|
//!uniform sampler2D voxels_shadows;
|
||||||
#endif
|
#endif
|
||||||
#ifdef _LTC
|
#ifdef _LTC
|
||||||
#include "std/ltc.glsl"
|
#include "std/ltc.glsl"
|
||||||
@ -22,63 +23,46 @@
|
|||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
#include "std/light_common.glsl"
|
#include "std/light_common.glsl"
|
||||||
#endif
|
#endif
|
||||||
#ifdef _VoxelShadow
|
|
||||||
#include "std/conetrace.glsl"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
#ifndef _LTC
|
#ifndef _LTC
|
||||||
uniform sampler2DShadow shadowMapSpot[1];
|
uniform sampler2DShadow shadowMapSpot[1];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapSpotTransparent[1];
|
uniform sampler2D shadowMapSpotTransparent[1];
|
||||||
#endif
|
uniform mat4 LWVPSpot[1];
|
||||||
uniform mat4 LWVPSpotArray[1];
|
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
uniform samplerCubeShadow shadowMapPoint[1];
|
uniform samplerCubeShadow shadowMapPoint[1];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform samplerCube shadowMapPointTransparent[1];
|
uniform samplerCube shadowMapPointTransparent[1];
|
||||||
#endif
|
|
||||||
uniform vec2 lightProj;
|
uniform vec2 lightProj;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
#ifdef _SingleAtlas
|
#ifdef _SingleAtlas
|
||||||
//!uniform sampler2DShadow shadowMapAtlas;
|
//!uniform sampler2DShadow shadowMapAtlas;
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
//!uniform sampler2D shadowMapAtlasTransparent;
|
//!uniform sampler2D shadowMapAtlasTransparent;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
uniform vec2 lightProj;
|
uniform vec2 lightProj;
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
uniform sampler2DShadow shadowMapAtlasPoint;
|
uniform sampler2DShadow shadowMapAtlasPoint;
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapAtlasPointTransparent;
|
uniform sampler2D shadowMapAtlasPointTransparent;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
uniform samplerCubeShadow shadowMapPoint[4];
|
uniform samplerCubeShadow shadowMapPoint[4];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform samplerCube shadowMapPointTransparent[4];
|
uniform samplerCube shadowMapPointTransparent[4];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
uniform sampler2DShadow shadowMapAtlasSpot;
|
uniform sampler2DShadow shadowMapAtlasSpot;
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapAtlasSpotTransparent;
|
uniform sampler2D shadowMapAtlasSpotTransparent;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
uniform sampler2DShadow shadowMapSpot[4];
|
uniform sampler2DShadow shadowMapSpot[4];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapSpotTransparent[4];
|
uniform sampler2D shadowMapSpotTransparent[4];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -95,16 +79,12 @@ uniform sampler2D sltcMag;
|
|||||||
#ifndef _Spot
|
#ifndef _Spot
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
uniform sampler2DShadow shadowMapSpot[1];
|
uniform sampler2DShadow shadowMapSpot[1];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapSpotTransparent[1];
|
uniform sampler2D shadowMapSpotTransparent[1];
|
||||||
#endif
|
uniform mat4 LWVPSpot[1];
|
||||||
uniform mat4 LWVPSpotArray[1];
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
|
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
|
||||||
#endif
|
|
||||||
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
uniform mat4 LWVPSpotArray[maxLightsCluster];
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -114,16 +94,13 @@ uniform sampler2D sltcMag;
|
|||||||
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
|
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
|
const vec3 albedo, const float rough, const float spec, const vec3 f0
|
||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
, int index, float bias, bool receiveShadow
|
, int index, float bias, bool receiveShadow, bool transparent
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, bool transparent
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Spot
|
#ifdef _Spot
|
||||||
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
|
||||||
#endif
|
#endif
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity
|
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount]
|
||||||
#endif
|
#endif
|
||||||
#ifdef _MicroShadowing
|
#ifdef _MicroShadowing
|
||||||
, float occ
|
, float occ
|
||||||
@ -153,12 +130,14 @@ 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);
|
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||||
#else
|
#else
|
||||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
vec3 F0 = surfaceF0(albedo, spec); // spec used as the metalness value
|
||||||
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
|
|
||||||
|
vec3 direct = burleyDiffuseBRDF(n, v, l, albedo, rough) * (1.0 - spec) +
|
||||||
|
specularBRDF(n, v, l, f0, rough) * spec;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
direct *= attenuate(distance(p, lp));
|
direct *= attenuate(distance(p, lp));
|
||||||
direct *= min(lightCol, vec3(100.0));
|
direct *= lightCol;
|
||||||
|
|
||||||
#ifdef _MicroShadowing
|
#ifdef _MicroShadowing
|
||||||
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
|
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
|
||||||
@ -169,67 +148,22 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
vec3 lightDir = l;
|
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
|
||||||
#ifdef _Spot
|
|
||||||
if (isSpot)
|
|
||||||
lightDir = spotDir;
|
|
||||||
#endif
|
|
||||||
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _LTC
|
#ifdef _LTC
|
||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
if (receiveShadow) {
|
if (receiveShadow) {
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||||
direct *= shadowTest(shadowMapSpot[0],
|
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
shadowMapSpotTransparent[0],
|
|
||||||
#endif
|
|
||||||
lPos.xyz / lPos.w, bias
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
|
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||||
#ifdef _ShadowMapTransparent
|
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||||
shadowMapSpotTransparent[0],
|
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||||
#endif
|
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||||
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
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -243,76 +177,25 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
|||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
if (receiveShadow) {
|
if (receiveShadow) {
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||||
direct *= shadowTest(shadowMapSpot[0],
|
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
shadowMapSpotTransparent[0],
|
|
||||||
#endif
|
|
||||||
lPos.xyz / lPos.w, bias
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
direct *= shadowTest(
|
direct *= shadowTest(
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
|
||||||
#else
|
#else
|
||||||
shadowMapAtlas, shadowMapAtlasTransparent
|
shadowMapAtlas, shadowMapAtlasTransparent
|
||||||
#endif
|
#endif
|
||||||
#else
|
, lPos.xyz / lPos.w, bias, transparent
|
||||||
#ifndef _SingleAtlas
|
|
||||||
shadowMapAtlasSpot
|
|
||||||
#else
|
|
||||||
shadowMapAtlas
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
, lPos.xyz / lPos.w, bias
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
|
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
|
||||||
#ifdef _ShadowMapTransparent
|
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
|
||||||
shadowMapSpotTransparent[0],
|
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
|
||||||
#endif
|
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
|
||||||
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
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -329,75 +212,24 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
|||||||
if (receiveShadow) {
|
if (receiveShadow) {
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
#ifndef _Spot
|
#ifndef _Spot
|
||||||
direct *= PCFCube(shadowMapPoint[0],
|
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
shadowMapPointTransparent[0],
|
|
||||||
#endif
|
|
||||||
ld, -l, bias, lightProj, n
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
direct *= PCFFakeCube(
|
direct *= PCFFakeCube(
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
#ifndef _SingleAtlas
|
#ifndef _SingleAtlas
|
||||||
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
|
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
|
||||||
#else
|
#else
|
||||||
shadowMapAtlas, shadowMapAtlasTransparent
|
shadowMapAtlas, shadowMapAtlasTransparent
|
||||||
#endif
|
#endif
|
||||||
#else
|
, ld, -l, bias, lightProj, n, index, transparent
|
||||||
#ifndef _SingleAtlas
|
|
||||||
shadowMapAtlasPoint
|
|
||||||
#else
|
|
||||||
shadowMapAtlas
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
, ld, -l, bias, lightProj, n, index
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
if (index == 0) direct *= PCFCube(shadowMapPoint[0],
|
if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
|
||||||
#ifdef _ShadowMapTransparent
|
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent);
|
||||||
shadowMapPointTransparent[0],
|
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent);
|
||||||
#endif
|
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent);
|
||||||
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
|
#endif
|
||||||
}
|
}
|
||||||
@ -406,275 +238,4 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
|||||||
return direct;
|
return direct;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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
|
|
||||||
#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 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;
|
|
||||||
#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 * 2, 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 * 2, 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
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return direct;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _Spot
|
|
||||||
if (isSpot) {
|
|
||||||
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
|
|
||||||
|
|
||||||
#ifdef _ShadowMap
|
|
||||||
if (receiveShadow) {
|
|
||||||
#ifdef _SinglePoint
|
|
||||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 2, 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 * 2, 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
|
|
||||||
}
|
|
||||||
#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
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,6 +7,12 @@ float hash(const vec2 p) {
|
|||||||
return fract(sin(h) * 43758.5453123);
|
return fract(sin(h) * 43758.5453123);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float hash12(vec2 p) {
|
||||||
|
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||||
|
p3 += dot(p3, p3.yzx + 33.33);
|
||||||
|
return fract((p3.x + p3.y) * p3.z);
|
||||||
|
}
|
||||||
|
|
||||||
vec2 envMapEquirect(const vec3 normal) {
|
vec2 envMapEquirect(const vec3 normal) {
|
||||||
const float PI = 3.1415926535;
|
const float PI = 3.1415926535;
|
||||||
const float PI2 = PI * 2.0;
|
const float PI2 = PI * 2.0;
|
||||||
@ -27,9 +33,9 @@ vec2 rand2(const vec2 coord) {
|
|||||||
return vec2(noiseX, noiseY);
|
return vec2(noiseX, noiseY);
|
||||||
}
|
}
|
||||||
|
|
||||||
float linearize(const float depth, vec2 cameraProj) {
|
float linearize(float depth, vec2 cameraProj) {
|
||||||
// to viewz
|
return cameraProj.y / (cameraProj.x - max(depth, 1e-6));
|
||||||
return cameraProj.y / (depth - cameraProj.x);
|
//return cameraProj.y / (cameraProj.x - depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
float attenuate(const float dist) {
|
float attenuate(const float dist) {
|
||||||
|
|||||||
@ -5,7 +5,6 @@ uniform vec2 morphDataDim;
|
|||||||
uniform vec4 morphWeights[8];
|
uniform vec4 morphWeights[8];
|
||||||
|
|
||||||
void getMorphedVertex(vec2 uvCoord, inout vec3 A){
|
void getMorphedVertex(vec2 uvCoord, inout vec3 A){
|
||||||
vec3 totalDelta = vec3(0.0);
|
|
||||||
for(int i = 0; i<8; i++ )
|
for(int i = 0; i<8; i++ )
|
||||||
{
|
{
|
||||||
vec4 tempCoordY = vec4( uvCoord.y - (i * 4) * morphDataDim.y,
|
vec4 tempCoordY = vec4( uvCoord.y - (i * 4) * morphDataDim.y,
|
||||||
@ -14,28 +13,21 @@ void getMorphedVertex(vec2 uvCoord, inout vec3 A){
|
|||||||
uvCoord.y - (i * 4 + 3) * morphDataDim.y);
|
uvCoord.y - (i * 4 + 3) * morphDataDim.y);
|
||||||
|
|
||||||
vec3 morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.x)).rgb * morphScaleOffset.x + morphScaleOffset.y;
|
vec3 morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.x)).rgb * morphScaleOffset.x + morphScaleOffset.y;
|
||||||
totalDelta += morphWeights[i].x * morph;
|
A += morphWeights[i].x * morph;
|
||||||
|
|
||||||
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.y)).rgb * morphScaleOffset.x + morphScaleOffset.y;
|
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.y)).rgb * morphScaleOffset.x + morphScaleOffset.y;
|
||||||
totalDelta += morphWeights[i].y * morph;
|
A += morphWeights[i].y * morph;
|
||||||
|
|
||||||
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.z)).rgb * morphScaleOffset.x + morphScaleOffset.y;
|
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.z)).rgb * morphScaleOffset.x + morphScaleOffset.y;
|
||||||
totalDelta += morphWeights[i].z * morph;
|
A += morphWeights[i].z * morph;
|
||||||
|
|
||||||
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.w)).rgb * morphScaleOffset.x + morphScaleOffset.y;
|
morph = texture(morphDataPos, vec2(uvCoord.x, tempCoordY.w)).rgb * morphScaleOffset.x + morphScaleOffset.y;
|
||||||
totalDelta += morphWeights[i].w * morph;
|
A += morphWeights[i].w * morph;
|
||||||
}
|
}
|
||||||
//float deltaLength = length(totalDelta);
|
|
||||||
//if (deltaLength > 5.0) {
|
|
||||||
// clamp corrupted data
|
|
||||||
//totalDelta = normalize(totalDelta) * 5.0;
|
|
||||||
//}
|
|
||||||
A += totalDelta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getMorphedNormal(vec2 uvCoord, vec3 oldNor, inout vec3 morphNor){
|
void getMorphedNormal(vec2 uvCoord, vec3 oldNor, inout vec3 morphNor){
|
||||||
|
|
||||||
vec3 normalDelta = vec3(0.0);
|
|
||||||
for(int i = 0; i<8; i++ )
|
for(int i = 0; i<8; i++ )
|
||||||
{
|
{
|
||||||
vec4 tempCoordY = vec4( uvCoord.y - (i * 4) * morphDataDim.y,
|
vec4 tempCoordY = vec4( uvCoord.y - (i * 4) * morphDataDim.y,
|
||||||
@ -43,11 +35,19 @@ void getMorphedNormal(vec2 uvCoord, vec3 oldNor, inout vec3 morphNor){
|
|||||||
uvCoord.y - (i * 4 + 2) * morphDataDim.y,
|
uvCoord.y - (i * 4 + 2) * morphDataDim.y,
|
||||||
uvCoord.y - (i * 4 + 3) * morphDataDim.y);
|
uvCoord.y - (i * 4 + 3) * morphDataDim.y);
|
||||||
|
|
||||||
normalDelta += morphWeights[i].x * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.x)).rgb * 2.0 - 1.0);
|
vec3 norm = oldNor + morphWeights[i].x * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.x)).rgb * 2.0 - 1.0);
|
||||||
normalDelta += morphWeights[i].y * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.y)).rgb * 2.0 - 1.0);
|
morphNor += norm;
|
||||||
normalDelta += morphWeights[i].z * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.z)).rgb * 2.0 - 1.0);
|
|
||||||
normalDelta += morphWeights[i].w * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.w)).rgb * 2.0 - 1.0);
|
norm = oldNor + morphWeights[i].y * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.y)).rgb * 2.0 - 1.0);
|
||||||
|
morphNor += norm;
|
||||||
|
|
||||||
|
norm = oldNor + morphWeights[i].z * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.z)).rgb * 2.0 - 1.0);
|
||||||
|
morphNor += norm;
|
||||||
|
|
||||||
|
norm = oldNor + morphWeights[i].w * (texture(morphDataNor, vec2(uvCoord.x, tempCoordY.w)).rgb * 2.0 - 1.0);
|
||||||
|
morphNor += norm;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
morphNor = normalize(oldNor + normalDelta);
|
morphNor = normalize(morphNor);
|
||||||
}
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
<EFBFBD><EFBFBD>shader_datas<EFBFBD><EFBFBD><EFBFBD>name<EFBFBD>copy_pass<EFBFBD>contexts<EFBFBD><EFBFBD><EFBFBD>name<EFBFBD>copy_pass<EFBFBD>constants<EFBFBD><EFBFBD>texture_units<EFBFBD><EFBFBD><EFBFBD>name<EFBFBD>tex<EFBFBD>vertex_elements<EFBFBD><EFBFBD><EFBFBD>data<EFBFBD>float2<EFBFBD>name<EFBFBD>pos<EFBFBD>vertex_shader<EFBFBD>pass.vert<72>fragment_shader<65>pass_copy.frag<61>depth_write¬compare_mode<64>always<79>cull_mode<64>none<6E><65>name<6D>compositor_pass<73>contexts<74><73><EFBFBD>name<6D>compositor_pass<73>constants<74><73>texture_units<74><73><EFBFBD>name<6D>tex<65>vertex_elements<74><73><EFBFBD>data<74>float2<74>name<6D>pos<6F>vertex_shader<65>compositor_pass.vert<72>fragment_shader<65>compositor_pass.frag<61>depth_write¬compare_mode<64>always<79>cull_mode<64>none<6E><65>name<6D>deferred_light<68>contexts<74><73><EFBFBD>name<6D>deferred_light<68>constants<74><73><EFBFBD>type<70>mat4<74>name<6D>invVP<56>link<6E>_inverseViewProjectionMatrix<69><78>type<70>vec3<63>name<6D>eye<79>link<6E>_cameraPosition<6F><6E>type<70>float<61>name<6D>envmapStrength<74>link<6E>_envmapStrength<74><68>type<70>floats<74>name<6D>shirr<72>link<6E>_envmapIrradiance<63><65>type<70>int<6E>name<6D>envmapNumMipmaps<70>link<6E>_envmapNumMipmaps<70><73>type<70>vec2<63>name<6D>cameraProj<6F>link<6E>_cameraPlaneProj<6F><6A>type<70>vec3<63>name<6D>eyeLook<6F>link<6E>_cameraLook<6F><6B>type<70>vec2<63>name<6D>lightProj<6F>link<6E>_lightPlaneProj<6F><6A>type<70>vec3<63>name<6D>pointPos<6F>link<6E>_pointPosition<6F><6E>type<70>vec3<63>name<6D>pointCol<6F>link<6E>_pointColor<6F><72>type<70>float<61>name<6D>pointBias<61>link<6E>_pointShadowsBias<61>texture_units<74><73><EFBFBD>name<6D>gbufferD<72><44>name<6D>gbuffer0<72><30>name<6D>gbuffer1<72><31>name<6D>senvmapBrdf<64>link<6E>$brdf.png<6E><67>name<6D>senvmapRadiance<63>link<6E>_envmapRadiance<63><65>name<6D>shadowMapPoint[0]<5D>vertex_elements<74><73><EFBFBD>data<74>float2<74>name<6D>pos<6F>vertex_shader<65>pass_viewray.vert<72>fragment_shader<65>deferred_light.frag<61>color_attachments<74><73>RGBA64<36>depth_write¬compare_mode<64>always<79>cull_mode<64>none<6E><65>name<6D>water_pass<73>contexts<74><73><EFBFBD>name<6D>water_pass<73>constants<74><73><EFBFBD>type<70>mat4<74>name<6D>invVP<56><50>type<70>vec3<63>name<6D>eye<79>link<6E>_cameraPosition<6F><6E>type<70>float<61>name<6D>time<6D>link<6E>_time<6D><65>type<70>float<61>name<6D>holoOverallStrength<74><68>type<70>vec2<63>name<6D>cameraProj<6F>link<6E>_cameraPlaneProj<6F><6A>type<70>vec3<63>name<6D>eyeLook<6F>link<6E>_cameraLook<6F><6B>type<70>vec3<63>name<6D>ld<6C>link<6E>_lightDirection<6F>texture_units<74><73><EFBFBD>name<6D>tex<65><78>name<6D>gbufferD<72><44>name<6D>gbuffer0<72>vertex_elements<74><73><EFBFBD>data<74>float2<74>name<6D>pos<6F>vertex_shader<65>pass_viewray.vert<72>fragment_shader<65>water_pass.frag<61>depth_write¬compare_mode<64>always<79>cull_mode<64>none<6E>blend_source<63>source_alpha<68>blend_destination<6F>inverse_source_alpha<68>blend_operation<6F>add<64>alpha_blend_source<63>blend_one<6E>alpha_blend_destination<6F>blend_one<6E>alpha_blend_operation<6F>add<64><64>contexts<74><73><EFBFBD>name<6D>World_World<6C>depth_write¬compare_mode<64>less<73>cull_mode<64>clockwise<73>vertex_elements<74><73><EFBFBD>name<6D>pos<6F>data<74>float3<74><33>name<6D>nor<6F>data<74>float3<74>color_attachments<74><73>_HDR<44>texture_units<74><73>constants<74><73><EFBFBD>name<6D>SMVP<56>type<70>mat4<74>link<6E>_skydomeMatrix<69>vertex_shader<65>World_World.vert<72>fragment_shader<65>World_World.frag<61>name<6D>World_World
|
|
||||||
@ -23,59 +23,6 @@ uniform vec2 smSizeUniform;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
// PCF that clamps samples to tile boundaries to prevent bleeding
|
|
||||||
vec3 PCFTileAware(sampler2DShadow shadowMap,
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
sampler2D shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
const vec2 uv, const float compare, const vec2 smSize,
|
|
||||||
const vec2 tileMin, const vec2 tileMax
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, const bool transparent
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
vec3 result = vec3(0.0);
|
|
||||||
vec2 offset;
|
|
||||||
|
|
||||||
offset = vec2(-1.0, -1.0) / smSize;
|
|
||||||
result.x = texture(shadowMap, vec3(clamp(uv + offset, tileMin, tileMax), compare));
|
|
||||||
|
|
||||||
offset = vec2(-1.0, 0.0) / smSize;
|
|
||||||
result.x += texture(shadowMap, vec3(clamp(uv + offset, tileMin, tileMax), compare));
|
|
||||||
|
|
||||||
offset = vec2(-1.0, 1.0) / smSize;
|
|
||||||
result.x += texture(shadowMap, vec3(clamp(uv + offset, tileMin, tileMax), compare));
|
|
||||||
|
|
||||||
offset = vec2(0.0, -1.0) / smSize;
|
|
||||||
result.x += texture(shadowMap, vec3(clamp(uv + offset, tileMin, tileMax), compare));
|
|
||||||
|
|
||||||
result.x += texture(shadowMap, vec3(uv, compare));
|
|
||||||
|
|
||||||
offset = vec2(0.0, 1.0) / smSize;
|
|
||||||
result.x += texture(shadowMap, vec3(clamp(uv + offset, tileMin, tileMax), compare));
|
|
||||||
|
|
||||||
offset = vec2(1.0, -1.0) / smSize;
|
|
||||||
result.x += texture(shadowMap, vec3(clamp(uv + offset, tileMin, tileMax), compare));
|
|
||||||
|
|
||||||
offset = vec2(1.0, 0.0) / smSize;
|
|
||||||
result.x += texture(shadowMap, vec3(clamp(uv + offset, tileMin, tileMax), compare));
|
|
||||||
|
|
||||||
offset = vec2(1.0, 1.0) / smSize;
|
|
||||||
result.x += texture(shadowMap, vec3(clamp(uv + offset, tileMin, tileMax), compare));
|
|
||||||
|
|
||||||
result = result.xxx / 9.0;
|
|
||||||
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
if (transparent == false) {
|
|
||||||
vec4 shadowmap_transparent = texture(shadowMapTransparent, uv);
|
|
||||||
if (shadowmap_transparent.a < compare)
|
|
||||||
result *= shadowmap_transparent.rgb;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://www.khronos.org/registry/OpenGL/specs/gl/glspec20.pdf // p:168
|
// 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/
|
// https://www.gamedev.net/forums/topic/687535-implementing-a-cube-map-lookup-function/5337472/
|
||||||
vec2 sampleCube(vec3 dir, out int faceIndex) {
|
vec2 sampleCube(vec3 dir, out int faceIndex) {
|
||||||
@ -111,15 +58,7 @@ vec2 sampleCube(vec3 dir, out int faceIndex) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vec3 PCF(sampler2DShadow shadowMap,
|
vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 uv, const float compare, const vec2 smSize, const bool transparent) {
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
sampler2D shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
const vec2 uv, const float compare, const vec2 smSize
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, const bool transparent
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
vec3 result = vec3(0.0);
|
vec3 result = vec3(0.0);
|
||||||
result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare));
|
result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare));
|
||||||
result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare));
|
result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare));
|
||||||
@ -132,13 +71,11 @@ vec3 PCF(sampler2DShadow shadowMap,
|
|||||||
result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare));
|
result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare));
|
||||||
result = result.xxx / 9.0;
|
result = result.xxx / 9.0;
|
||||||
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
if (transparent == false) {
|
if (transparent == false) {
|
||||||
vec4 shadowmap_transparent = texture(shadowMapTransparent, uv);
|
vec4 shadowmap_transparent = texture(shadowMapTransparent, uv);
|
||||||
if (shadowmap_transparent.a < compare)
|
if (shadowmap_transparent.a < compare)
|
||||||
result *= shadowmap_transparent.rgb;
|
result *= shadowmap_transparent.rgb;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -150,15 +87,41 @@ float lpToDepth(vec3 lp, const vec2 lightProj) {
|
|||||||
return zcomp * 0.5 + 0.5;
|
return zcomp * 0.5 + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 PCFCube(samplerCubeShadow shadowMapCube,
|
#ifndef _ShadowMapAtlas
|
||||||
#ifdef _ShadowMapTransparent
|
vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, vec3 lp, vec3 ml, float bias, vec2 lightProj, vec3 n, const bool transparent) {
|
||||||
samplerCube shadowMapCubeTransparent,
|
const float s = shadowmapCubePcfSize;
|
||||||
|
float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
||||||
|
ml = ml + n * bias * 20;
|
||||||
|
#ifdef _InvY
|
||||||
|
ml.y = -ml.y;
|
||||||
#endif
|
#endif
|
||||||
const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n
|
|
||||||
#ifdef _ShadowMapTransparent
|
float shadowFactor = 0.0;
|
||||||
, const bool transparent
|
shadowFactor = texture(shadowMapCube, vec4(ml, compare));
|
||||||
|
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare));
|
||||||
|
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare));
|
||||||
|
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare));
|
||||||
|
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare));
|
||||||
|
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare));
|
||||||
|
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare));
|
||||||
|
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare));
|
||||||
|
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
|
||||||
|
shadowFactor /= 9.0;
|
||||||
|
|
||||||
|
vec3 result = vec3(shadowFactor);
|
||||||
|
|
||||||
|
if (transparent == false) {
|
||||||
|
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
|
||||||
|
if (shadowmap_transparent.a < compare)
|
||||||
|
result *= shadowmap_transparent.rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
) {
|
|
||||||
|
#ifdef _ShadowMapAtlas
|
||||||
|
vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) {
|
||||||
const float s = shadowmapCubePcfSize; // TODO: incorrect...
|
const float s = shadowmapCubePcfSize; // TODO: incorrect...
|
||||||
float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
||||||
ml = ml + n * bias * 20;
|
ml = ml + n * bias * 20;
|
||||||
@ -177,18 +140,16 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube,
|
|||||||
result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
|
result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
|
||||||
result = result.xxx / 9.0;
|
result = result.xxx / 9.0;
|
||||||
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
if (transparent == false) {
|
if (transparent == false) {
|
||||||
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
|
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
|
||||||
if (shadowmap_transparent.a < compare)
|
if (shadowmap_transparent.a < compare)
|
||||||
result *= shadowmap_transparent.rgb;
|
result *= shadowmap_transparent.rgb;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _ShadowMapAtlas
|
|
||||||
// transform "out-of-bounds" coordinates to the correct face/coordinate system
|
// transform "out-of-bounds" coordinates to the correct face/coordinate system
|
||||||
// https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png
|
// https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png
|
||||||
vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) {
|
vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) {
|
||||||
@ -282,31 +243,21 @@ vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) {
|
|||||||
return uv;
|
return uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 PCFFakeCube(sampler2DShadow shadowMap,
|
vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index, const bool transparent) {
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
sampler2D shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, const bool transparent
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
const vec2 smSize = smSizeUniform; // TODO: incorrect...
|
const vec2 smSize = smSizeUniform; // TODO: incorrect...
|
||||||
const float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
const float compare = lpToDepth(lp, lightProj) - bias * 1.5;
|
||||||
ml = ml + n * bias * 20;
|
ml = ml + n * bias * 20;
|
||||||
|
|
||||||
int faceIndex = 0;
|
int faceIndex = 0;
|
||||||
const int lightIndex = index * 6;
|
const int lightIndex = index * 6;
|
||||||
const vec2 uv = sampleCube(ml, faceIndex);
|
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
|
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;
|
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
|
||||||
#ifdef _FlipY
|
#ifdef _FlipY
|
||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) {
|
|
||||||
return vec3(1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 result = vec3(0.0);
|
vec3 result = vec3(0.0);
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
||||||
// soft shadowing
|
// soft shadowing
|
||||||
@ -319,6 +270,14 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap,
|
|||||||
#endif
|
#endif
|
||||||
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
||||||
|
|
||||||
|
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 1.0) / smSize)));
|
||||||
|
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
||||||
|
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
||||||
|
#ifdef _FlipY
|
||||||
|
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
||||||
|
#endif
|
||||||
|
result.x += texture(shadowMap, vec3(uvtiled, compare));
|
||||||
|
|
||||||
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize)));
|
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize)));
|
||||||
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
|
||||||
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
|
||||||
@ -375,72 +334,30 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap,
|
|||||||
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
if (transparent == false) {
|
if (transparent == false) {
|
||||||
vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled);
|
vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled);
|
||||||
if (shadowmap_transparent.a < compare)
|
if (shadowmap_transparent.a < compare)
|
||||||
result *= shadowmap_transparent.rgb;
|
result *= shadowmap_transparent.rgb;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _ShadowMapAtlas
|
vec3 shadowTest(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lPos, const float shadowsBias, const bool transparent) {
|
||||||
uniform vec4 tileBounds;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
vec3 shadowTest(sampler2DShadow shadowMap,
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
sampler2D shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
const vec3 lPos, const float shadowsBias
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, const bool transparent
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0);
|
|
||||||
|
|
||||||
#ifdef _ShadowMapAtlas
|
|
||||||
// use tile PCF
|
|
||||||
#ifdef _SMSizeUniform
|
|
||||||
vec2 smSizeAtlas = smSizeUniform;
|
|
||||||
#else
|
|
||||||
const vec2 smSizeAtlas = shadowmapSize;
|
|
||||||
#endif
|
|
||||||
return PCFTileAware(shadowMap,
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
lPos.xy, lPos.z - shadowsBias, smSizeAtlas,
|
|
||||||
tileBounds.xy, tileBounds.zw
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#else
|
|
||||||
// use PCF for non-atlas shadows
|
|
||||||
#ifdef _SMSizeUniform
|
#ifdef _SMSizeUniform
|
||||||
vec2 smSize = smSizeUniform;
|
vec2 smSize = smSizeUniform;
|
||||||
#else
|
#else
|
||||||
const vec2 smSize = shadowmapSize;
|
const vec2 smSize = shadowmapSize;
|
||||||
#endif
|
#endif
|
||||||
return PCF(shadowMap,
|
if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0);
|
||||||
#ifdef _ShadowMapTransparent
|
return PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent);
|
||||||
shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
lPos.xy, lPos.z - shadowsBias, smSize
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _CSM
|
#ifdef _CSM
|
||||||
mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
||||||
const int c = shadowmapCascades;
|
const int c = shadowmapCascades;
|
||||||
|
|
||||||
// Get cascade index
|
// Get cascade index
|
||||||
// TODO: use bounding box slice selection instead of sphere
|
// TODO: use bounding box slice selection instead of sphere
|
||||||
const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3));
|
const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3));
|
||||||
@ -456,26 +373,21 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
|||||||
float(d > casData[c * 4].z),
|
float(d > casData[c * 4].z),
|
||||||
float(d > casData[c * 4].w));
|
float(d > casData[c * 4].w));
|
||||||
casi = int(min(dot(ci, comp), c));
|
casi = int(min(dot(ci, comp), c));
|
||||||
|
|
||||||
// Get cascade mat
|
// Get cascade mat
|
||||||
casIndex = casi * 4;
|
casIndex = casi * 4;
|
||||||
|
|
||||||
return mat4(
|
return mat4(
|
||||||
casData[casIndex ],
|
casData[casIndex ],
|
||||||
casData[casIndex + 1],
|
casData[casIndex + 1],
|
||||||
casData[casIndex + 2],
|
casData[casIndex + 2],
|
||||||
casData[casIndex + 3]);
|
casData[casIndex + 3]);
|
||||||
|
|
||||||
// if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]);
|
// if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]);
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 shadowTestCascade(sampler2DShadow shadowMap,
|
vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 eye, const vec3 p, const float shadowsBias, const bool transparent) {
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
sampler2D shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
const vec3 eye, const vec3 p, const float shadowsBias
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, const bool transparent
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
#ifdef _SMSizeUniform
|
#ifdef _SMSizeUniform
|
||||||
vec2 smSize = smSizeUniform;
|
vec2 smSize = smSizeUniform;
|
||||||
#else
|
#else
|
||||||
@ -483,22 +395,16 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap,
|
|||||||
#endif
|
#endif
|
||||||
const int c = shadowmapCascades;
|
const int c = shadowmapCascades;
|
||||||
float d = distance(eye, p);
|
float d = distance(eye, p);
|
||||||
|
|
||||||
int casi;
|
int casi;
|
||||||
int casIndex;
|
int casIndex;
|
||||||
mat4 LWVP = getCascadeMat(d, casi, casIndex);
|
mat4 LWVP = getCascadeMat(d, casi, casIndex);
|
||||||
|
|
||||||
vec4 lPos = LWVP * vec4(p, 1.0);
|
vec4 lPos = LWVP * vec4(p, 1.0);
|
||||||
lPos.xyz /= lPos.w;
|
lPos.xyz /= lPos.w;
|
||||||
|
|
||||||
vec3 visibility = vec3(1.0);
|
vec3 visibility = vec3(1.0);
|
||||||
if (lPos.w > 0.0) visibility = PCF(shadowMap,
|
if (lPos.w > 0.0) visibility = PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent);
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
lPos.xy, lPos.z - shadowsBias, smSize
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
// Blend cascade
|
// Blend cascade
|
||||||
// https://github.com/TheRealMJP/Shadows
|
// https://github.com/TheRealMJP/Shadows
|
||||||
@ -517,21 +423,13 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap,
|
|||||||
vec4 lPos2 = LWVP2 * vec4(p, 1.0);
|
vec4 lPos2 = LWVP2 * vec4(p, 1.0);
|
||||||
lPos2.xyz /= lPos2.w;
|
lPos2.xyz /= lPos2.w;
|
||||||
vec3 visibility2 = vec3(1.0);
|
vec3 visibility2 = vec3(1.0);
|
||||||
// use lPos2 coordinates for second cascade, not lPos
|
if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, shadowMapTransparent, lPos2.xy, lPos2.z - shadowsBias, smSize, transparent);
|
||||||
if (lPos2.w > 0.0) visibility2 = PCF(shadowMap,
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
shadowMapTransparent,
|
|
||||||
#endif
|
|
||||||
lPos2.xy, lPos2.z - shadowsBias, smSize
|
|
||||||
#ifdef _ShadowMapTransparent
|
|
||||||
, transparent
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
float lerpAmt = smoothstep(0.0, blendThres, splitDist);
|
float lerpAmt = smoothstep(0.0, blendThres, splitDist);
|
||||||
return mix(visibility2, visibility, lerpAmt);
|
return mix(visibility2, visibility, lerpAmt);
|
||||||
}
|
}
|
||||||
return visibility;
|
return visibility;
|
||||||
|
|
||||||
// Visualize cascades
|
// Visualize cascades
|
||||||
// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0);
|
// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0);
|
||||||
// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0);
|
// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0);
|
||||||
|
|||||||
@ -11,8 +11,6 @@ vec3 uncharted2Tonemap(const vec3 x) {
|
|||||||
vec3 tonemapUncharted2(const vec3 color) {
|
vec3 tonemapUncharted2(const vec3 color) {
|
||||||
const float W = 11.2;
|
const float W = 11.2;
|
||||||
const float exposureBias = 2.0;
|
const float exposureBias = 2.0;
|
||||||
// TODO - Find out why black world value of 0.0,0.0,0.0 turns to white pixels
|
|
||||||
if (dot(color, color) < 0.001) return vec3(0.001);
|
|
||||||
vec3 curr = uncharted2Tonemap(exposureBias * color);
|
vec3 curr = uncharted2Tonemap(exposureBias * color);
|
||||||
vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
|
vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
|
||||||
return curr * whiteScale;
|
return curr * whiteScale;
|
||||||
|
|||||||
@ -13,80 +13,32 @@ out vec4 fragColor;
|
|||||||
|
|
||||||
const float SMAA_REPROJECTION_WEIGHT_SCALE = 30.0;
|
const float SMAA_REPROJECTION_WEIGHT_SCALE = 30.0;
|
||||||
|
|
||||||
// TODO: Move to a utility
|
|
||||||
bool isInvalidValue(float v) {
|
|
||||||
return (v != v) || (v > 65000.0) || (v < -65000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasInvalidValues(vec3 v) {
|
|
||||||
return isInvalidValue(v.x) || isInvalidValue(v.y) || isInvalidValue(v.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 current = textureLod(tex, texCoord, 0.0);
|
vec4 current = textureLod(tex, texCoord, 0.0);
|
||||||
|
|
||||||
current.rgb = clamp(current.rgb, vec3(0.0), vec3(10.0));
|
|
||||||
current.a = clamp(current.a, 0.0, 1.0);
|
|
||||||
if (hasInvalidValues(current.rgb)) {
|
|
||||||
current = vec4(0.0, 0.0, 0.0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _Veloc
|
#ifdef _Veloc
|
||||||
// Velocity is assumed to be calculated for motion blur, so we need to inverse it for reprojection
|
// Velocity is assumed to be calculated for motion blur, so we need to inverse it for reprojection
|
||||||
vec2 velocity = -textureLod(sveloc, texCoord, 0.0).rg;
|
vec2 velocity = -textureLod(sveloc, texCoord, 0.0).rg;
|
||||||
|
|
||||||
velocity = clamp(velocity, vec2(-1.0), vec2(1.0));
|
|
||||||
if (isInvalidValue(velocity.x) || isInvalidValue(velocity.y)) {
|
|
||||||
velocity = vec2(0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _InvY
|
#ifdef _InvY
|
||||||
velocity.y = -velocity.y;
|
velocity.y = -velocity.y;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reproject current coordinates and fetch previous pixel
|
// Reproject current coordinates and fetch previous pixel
|
||||||
vec2 prevCoord = texCoord + velocity;
|
vec4 previous = textureLod(tex2, texCoord + velocity, 0.0);
|
||||||
prevCoord = clamp(prevCoord, vec2(0.0), vec2(1.0));
|
|
||||||
vec4 previous = textureLod(tex2, prevCoord, 0.0);
|
|
||||||
|
|
||||||
previous.rgb = clamp(previous.rgb, vec3(0.0), vec3(10.0));
|
|
||||||
previous.a = clamp(previous.a, 0.0, 1.0);
|
|
||||||
if (hasInvalidValues(previous.rgb)) {
|
|
||||||
previous = current; // Fallback to current frame if previous is corrupted
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Attenuate the previous pixel if the velocity is different
|
||||||
#ifdef _SMAA
|
#ifdef _SMAA
|
||||||
float currentAlpha = clamp(current.a, 0.0, 1.0);
|
float delta = abs(current.a * current.a - previous.a * previous.a) / 5.0;
|
||||||
float previousAlpha = clamp(previous.a, 0.0, 1.0);
|
|
||||||
float delta = abs(currentAlpha * currentAlpha - previousAlpha * previousAlpha) / 5.0;
|
|
||||||
delta = clamp(delta, 0.0, 1.0); // Ensure delta is in valid range
|
|
||||||
#else
|
#else
|
||||||
const float delta = 0.0;
|
const float delta = 0.0;
|
||||||
#endif
|
#endif
|
||||||
|
float weight = 0.5 * clamp(1.0 - sqrt(delta) * SMAA_REPROJECTION_WEIGHT_SCALE, 0.0, 1.0);
|
||||||
|
|
||||||
float weight = 0.5 * clamp(1.0 - sqrt(max(delta, 0.0)) * SMAA_REPROJECTION_WEIGHT_SCALE, 0.0, 1.0);
|
// Blend the pixels according to the calculated weight:
|
||||||
|
fragColor = vec4(mix(current.rgb, previous.rgb, weight), 1.0);
|
||||||
vec3 blended = mix(current.rgb, previous.rgb, weight);
|
|
||||||
blended = clamp(blended, vec3(0.0), vec3(10.0));
|
|
||||||
if (hasInvalidValues(blended)) {
|
|
||||||
blended = current.rgb;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragColor = vec4(blended, 1.0);
|
|
||||||
#else
|
#else
|
||||||
vec4 previous = textureLod(tex2, texCoord, 0.0);
|
vec4 previous = textureLod(tex2, texCoord, 0.0);
|
||||||
|
fragColor = vec4(mix(current.rgb, previous.rgb, 0.5), 1.0);
|
||||||
previous.rgb = clamp(previous.rgb, vec3(0.0), vec3(10.0));
|
|
||||||
if (hasInvalidValues(previous.rgb)) {
|
|
||||||
previous.rgb = current.rgb;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 blended = mix(current.rgb, previous.rgb, 0.5);
|
|
||||||
blended = clamp(blended, vec3(0.0), vec3(10.0));
|
|
||||||
if (hasInvalidValues(blended)) {
|
|
||||||
blended = current.rgb;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragColor = vec4(blended, 1.0);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,11 +11,6 @@
|
|||||||
#include "std/light_common.glsl"
|
#include "std/light_common.glsl"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _CPostprocess
|
|
||||||
uniform vec3 PPComp11;
|
|
||||||
uniform vec4 PPComp17;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform sampler2D gbufferD;
|
uniform sampler2D gbufferD;
|
||||||
uniform sampler2D snoise;
|
uniform sampler2D snoise;
|
||||||
|
|
||||||
@ -92,13 +87,7 @@ out float fragColor;
|
|||||||
const float tScat = 0.08;
|
const float tScat = 0.08;
|
||||||
const float tAbs = 0.0;
|
const float tAbs = 0.0;
|
||||||
const float tExt = tScat + tAbs;
|
const float tExt = tScat + tAbs;
|
||||||
#ifdef _CPostprocess
|
|
||||||
float stepLen = 1.0 / int(PPComp11.y);
|
|
||||||
float AirTurbidity = PPComp17.w;
|
|
||||||
#else
|
|
||||||
const float stepLen = 1.0 / volumSteps;
|
const float stepLen = 1.0 / volumSteps;
|
||||||
float AirTurbidity = volumAirTurbidity;
|
|
||||||
#endif
|
|
||||||
const float lighting = 0.4;
|
const float lighting = 0.4;
|
||||||
|
|
||||||
void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatteredLightAmount, float stepLenWorld, vec3 viewVecNorm) {
|
void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatteredLightAmount, float stepLenWorld, vec3 viewVecNorm) {
|
||||||
@ -173,5 +162,5 @@ void main() {
|
|||||||
rayStep(curPos, curOpticalDepth, scatteredLightAmount, stepLenWorld, viewVecNorm);
|
rayStep(curPos, curOpticalDepth, scatteredLightAmount, stepLenWorld, viewVecNorm);
|
||||||
}
|
}
|
||||||
|
|
||||||
fragColor = scatteredLightAmount * AirTurbidity;
|
fragColor = scatteredLightAmount * volumAirTurbidity;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,16 +140,6 @@
|
|||||||
"link": "_biasLightWorldViewProjectionMatrixSpot3",
|
"link": "_biasLightWorldViewProjectionMatrixSpot3",
|
||||||
"ifndef": ["_ShadowMapAtlas"],
|
"ifndef": ["_ShadowMapAtlas"],
|
||||||
"ifdef": ["_Spot", "_ShadowMap"]
|
"ifdef": ["_Spot", "_ShadowMap"]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PPComp11",
|
|
||||||
"link": "_PPComp11",
|
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "PPComp17",
|
|
||||||
"link": "_PPComp17",
|
|
||||||
"ifdef": ["_CPostprocess"]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"texture_params": [],
|
"texture_params": [],
|
||||||
|
|||||||
@ -33,7 +33,6 @@ uniform layout(r32ui) uimage3D voxelsLight;
|
|||||||
|
|
||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
uniform sampler2DShadow shadowMap;
|
uniform sampler2DShadow shadowMap;
|
||||||
uniform sampler2D shadowMapTransparent;
|
|
||||||
uniform sampler2DShadow shadowMapSpot;
|
uniform sampler2DShadow shadowMapSpot;
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
uniform sampler2DShadow shadowMapPoint;
|
uniform sampler2DShadow shadowMapPoint;
|
||||||
@ -87,28 +86,30 @@ float lpToDepth(vec3 lp, const vec2 lightProj) {
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
int res = voxelgiResolution.x;
|
int res = voxelgiResolution.x;
|
||||||
|
|
||||||
ivec3 dst = ivec3(gl_GlobalInvocationID.xyz);
|
ivec3 dst = ivec3(gl_GlobalInvocationID.xyz);
|
||||||
|
dst.y += clipmapLevel * res;
|
||||||
|
|
||||||
vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x;
|
vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution;
|
||||||
wposition = wposition * 2.0 - 1.0;
|
P = P * 2.0 - 1.0;
|
||||||
wposition *= float(clipmaps[int(clipmapLevel * 10)]);
|
P *= clipmaps[int(clipmapLevel * 10)];
|
||||||
wposition *= voxelgiResolution.x;
|
P *= voxelgiResolution;
|
||||||
wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]);
|
P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]);
|
||||||
|
|
||||||
float visibility;
|
vec3 visibility;
|
||||||
vec3 lp = lightPos -wposition;
|
vec3 lp = lightPos - P;
|
||||||
vec3 l;
|
vec3 l;
|
||||||
if (lightType == 0) { l = lightDir; visibility = 1.0; }
|
if (lightType == 0) { l = lightDir; visibility = vec3(1.0); }
|
||||||
else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); }
|
else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); }
|
||||||
|
|
||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
if (lightShadow == 1) {
|
if (lightShadow == 1) {
|
||||||
vec4 lightPosition = LVP * vec4(wposition, 1.0);
|
vec4 lightPosition = LVP * vec4(P, 1.0);
|
||||||
vec3 lPos = lightPosition.xyz / lightPosition.w;
|
vec3 lPos = lightPosition.xyz / lightPosition.w;
|
||||||
visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r;
|
visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr;
|
||||||
}
|
}
|
||||||
else if (lightShadow == 2) {
|
else if (lightShadow == 2) {
|
||||||
vec4 lightPosition = LVP * vec4(wposition, 1.0);
|
vec4 lightPosition = LVP * vec4(P, 1.0);
|
||||||
vec3 lPos = lightPosition.xyz / lightPosition.w;
|
vec3 lPos = lightPosition.xyz / lightPosition.w;
|
||||||
visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r;
|
visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r;
|
||||||
}
|
}
|
||||||
@ -129,7 +130,9 @@ void main() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
imageAtomicAdd(voxelsLight, dst, uint(visibility * lightColor.r * 255));
|
vec3 light = visibility * lightColor;
|
||||||
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255));
|
|
||||||
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255));
|
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), 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));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,14 +27,14 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
|
|||||||
#include "std/math.glsl"
|
#include "std/math.glsl"
|
||||||
#include "std/gbuffer.glsl"
|
#include "std/gbuffer.glsl"
|
||||||
#include "std/imageatomic.glsl"
|
#include "std/imageatomic.glsl"
|
||||||
#include "std/constants.glsl"
|
#include "std/voxels_constants.glsl"
|
||||||
|
|
||||||
#ifdef _VoxelGI
|
#ifdef _VoxelGI
|
||||||
uniform layout(rgba8) image3D voxelsB;
|
uniform layout(rgba8) image3D voxelsB;
|
||||||
uniform layout(rgba8) image3D voxelsOut;
|
uniform layout(rgba8) image3D voxelsOut;
|
||||||
#else
|
#else
|
||||||
uniform layout(r8) image3D voxelsB;
|
uniform layout(r16) image3D voxelsB;
|
||||||
uniform layout(r8) image3D voxelsOut;
|
uniform layout(r16) image3D voxelsOut;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform int clipmapLevel;
|
uniform int clipmapLevel;
|
||||||
|
|||||||
@ -29,38 +29,19 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|||||||
#include "std/gbuffer.glsl"
|
#include "std/gbuffer.glsl"
|
||||||
#include "std/imageatomic.glsl"
|
#include "std/imageatomic.glsl"
|
||||||
#include "std/conetrace.glsl"
|
#include "std/conetrace.glsl"
|
||||||
#include "std/brdf.glsl"
|
|
||||||
#include "std/shirr.glsl"
|
|
||||||
|
|
||||||
uniform sampler3D voxels;
|
uniform sampler3D voxels;
|
||||||
uniform sampler2D gbufferD;
|
uniform sampler2D gbufferD;
|
||||||
uniform sampler2D gbuffer0;
|
uniform sampler2D gbuffer0;
|
||||||
uniform layout(rgba8) image2D voxels_ao;
|
uniform layout(r8) image2D voxels_ao;
|
||||||
|
|
||||||
uniform float clipmaps[voxelgiClipmapCount * 10];
|
uniform float clipmaps[voxelgiClipmapCount * 10];
|
||||||
uniform mat4 InvVP;
|
uniform mat4 InvVP;
|
||||||
|
uniform vec2 cameraProj;
|
||||||
uniform vec3 eye;
|
uniform vec3 eye;
|
||||||
|
uniform vec3 eyeLook;
|
||||||
uniform vec2 postprocess_resolution;
|
uniform vec2 postprocess_resolution;
|
||||||
|
|
||||||
uniform sampler2D gbuffer1;
|
|
||||||
#ifdef _gbuffer2
|
|
||||||
uniform sampler2D gbuffer2;
|
|
||||||
#endif
|
|
||||||
uniform float envmapStrength;
|
|
||||||
#ifdef _Irr
|
|
||||||
uniform float shirr[7 * 4];
|
|
||||||
#endif
|
|
||||||
#ifdef _Brdf
|
|
||||||
uniform sampler2D senvmapBrdf;
|
|
||||||
#endif
|
|
||||||
#ifdef _Rad
|
|
||||||
uniform sampler2D senvmapRadiance;
|
|
||||||
uniform int envmapNumMipmaps;
|
|
||||||
#endif
|
|
||||||
#ifdef _EnvCol
|
|
||||||
uniform vec3 backgroundCol;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
const vec2 pixel = gl_GlobalInvocationID.xy;
|
const vec2 pixel = gl_GlobalInvocationID.xy;
|
||||||
vec2 uv = (pixel + 0.5) / postprocess_resolution;
|
vec2 uv = (pixel + 0.5) / postprocess_resolution;
|
||||||
@ -73,11 +54,12 @@ void main() {
|
|||||||
|
|
||||||
float x = uv.x * 2 - 1;
|
float x = uv.x * 2 - 1;
|
||||||
float y = uv.y * 2 - 1;
|
float y = uv.y * 2 - 1;
|
||||||
vec4 clipPos = vec4(x, y, depth, 1.0);
|
vec4 v = vec4(x, y, 1.0, 1.0);
|
||||||
vec4 worldPos = InvVP * clipPos;
|
v = vec4(InvVP * v);
|
||||||
vec3 P = worldPos.xyz / worldPos.w;
|
v.xyz /= v.w;
|
||||||
|
vec3 viewRay = v.xyz - eye;
|
||||||
|
|
||||||
vec3 v = normalize(eye - P);
|
vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
|
||||||
|
|
||||||
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
|
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
|
||||||
vec3 n;
|
vec3 n;
|
||||||
@ -85,89 +67,7 @@ void main() {
|
|||||||
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
|
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
|
||||||
n = normalize(n);
|
n = normalize(n);
|
||||||
|
|
||||||
float roughness = g0.b;
|
float occ = 1.0 - traceAO(P, n, voxels, clipmaps);
|
||||||
float metallic;
|
|
||||||
uint matid;
|
|
||||||
unpackFloatInt16(g0.a, metallic, matid);
|
|
||||||
|
|
||||||
vec4 g1 = textureLod(gbuffer1, uv, 0.0); // Basecolor.rgb, spec/occ
|
imageStore(voxels_ao, ivec2(pixel), vec4(occ));
|
||||||
vec2 occspec = unpackFloat2(g1.a);
|
|
||||||
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
|
|
||||||
vec3 f0 = surfaceF0(g1.rgb, metallic);
|
|
||||||
float dotNV = max(dot(n, v), 0.0);
|
|
||||||
|
|
||||||
#ifdef _gbuffer2
|
|
||||||
vec4 g2 = textureLod(gbuffer2, uv, 0.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MicroShadowing
|
|
||||||
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _Brdf
|
|
||||||
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
|
|
||||||
vec3 F = f0 * envBRDF.x + envBRDF.y;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Envmap
|
|
||||||
#ifdef _Irr
|
|
||||||
vec4 shPacked[7];
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
int base = i * 4;
|
|
||||||
shPacked[i] = vec4(
|
|
||||||
shirr[base],
|
|
||||||
shirr[base + 1],
|
|
||||||
shirr[base + 2],
|
|
||||||
shirr[base + 3]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
vec3 envl = shIrradiance(n, shPacked);
|
|
||||||
|
|
||||||
#ifdef _gbuffer2
|
|
||||||
if (g2.b < 0.5) {
|
|
||||||
envl = envl;
|
|
||||||
} else {
|
|
||||||
envl = vec3(0.0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _EnvTex
|
|
||||||
envl /= PI;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
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;
|
|
||||||
|
|
||||||
#ifdef _Brdf
|
|
||||||
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;
|
|
||||||
|
|
||||||
vec3 occ = envl * (1.0 - traceAO(P, n, voxels, clipmaps));
|
|
||||||
|
|
||||||
imageStore(voxels_ao, ivec2(pixel), vec4(occ, 1.0));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,8 +29,6 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|||||||
#include "std/gbuffer.glsl"
|
#include "std/gbuffer.glsl"
|
||||||
#include "std/imageatomic.glsl"
|
#include "std/imageatomic.glsl"
|
||||||
#include "std/conetrace.glsl"
|
#include "std/conetrace.glsl"
|
||||||
#include "std/brdf.glsl"
|
|
||||||
#include "std/shirr.glsl"
|
|
||||||
|
|
||||||
uniform sampler3D voxels;
|
uniform sampler3D voxels;
|
||||||
uniform sampler2D gbufferD;
|
uniform sampler2D gbufferD;
|
||||||
@ -39,44 +37,29 @@ uniform layout(rgba8) image2D voxels_diffuse;
|
|||||||
|
|
||||||
uniform float clipmaps[voxelgiClipmapCount * 10];
|
uniform float clipmaps[voxelgiClipmapCount * 10];
|
||||||
uniform mat4 InvVP;
|
uniform mat4 InvVP;
|
||||||
|
uniform vec2 cameraProj;
|
||||||
uniform vec3 eye;
|
uniform vec3 eye;
|
||||||
|
uniform vec3 eyeLook;
|
||||||
uniform vec2 postprocess_resolution;
|
uniform vec2 postprocess_resolution;
|
||||||
|
|
||||||
uniform sampler2D gbuffer1;
|
|
||||||
#ifdef _gbuffer2
|
|
||||||
uniform sampler2D gbuffer2;
|
|
||||||
#endif
|
|
||||||
uniform float envmapStrength;
|
|
||||||
#ifdef _Irr
|
|
||||||
uniform float shirr[7 * 4];
|
|
||||||
#endif
|
|
||||||
#ifdef _Brdf
|
|
||||||
uniform sampler2D senvmapBrdf;
|
|
||||||
#endif
|
|
||||||
#ifdef _Rad
|
|
||||||
uniform sampler2D senvmapRadiance;
|
|
||||||
uniform int envmapNumMipmaps;
|
|
||||||
#endif
|
|
||||||
#ifdef _EnvCol
|
|
||||||
uniform vec3 backgroundCol;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
const vec2 pixel = gl_GlobalInvocationID.xy;
|
const vec2 pixel = gl_GlobalInvocationID.xy;
|
||||||
vec2 uv = (pixel + 0.5) / postprocess_resolution;
|
vec2 uv = (pixel + 0.5) / postprocess_resolution;
|
||||||
#ifdef _InvY
|
#ifdef _InvY
|
||||||
uv.y = 1.0 - uv.y;
|
uv.y = 1.0 - uv.y
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
|
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
|
||||||
if (depth == 0.0) return;
|
if (depth == 0) return;
|
||||||
|
|
||||||
float x = uv.x * 2 - 1;
|
float x = uv.x * 2 - 1;
|
||||||
float y = uv.y * 2 - 1;
|
float y = uv.y * 2 - 1;
|
||||||
vec4 clipPos = vec4(x, y, depth, 1.0);
|
vec4 v = vec4(x, y, 1.0, 1.0);
|
||||||
vec4 worldPos = InvVP * clipPos;
|
v = vec4(InvVP * v);
|
||||||
vec3 P = worldPos.xyz / worldPos.w;
|
v.xyz /= v.w;
|
||||||
vec3 v = normalize(eye - P);
|
vec3 viewRay = v.xyz - eye;
|
||||||
|
|
||||||
|
vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
|
||||||
|
|
||||||
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
|
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
|
||||||
vec3 n;
|
vec3 n;
|
||||||
@ -84,94 +67,7 @@ void main() {
|
|||||||
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
|
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
|
||||||
n = normalize(n);
|
n = normalize(n);
|
||||||
|
|
||||||
float roughness = g0.b;
|
vec4 color = traceDiffuse(P, n, voxels, clipmaps);
|
||||||
float metallic;
|
|
||||||
uint matid;
|
|
||||||
unpackFloatInt16(g0.a, metallic, matid);
|
|
||||||
|
|
||||||
vec4 g1 = textureLod(gbuffer1, uv, 0.0); // Basecolor.rgb, spec/occ
|
imageStore(voxels_diffuse, ivec2(pixel), color);
|
||||||
vec2 occspec = unpackFloat2(g1.a);
|
|
||||||
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
|
|
||||||
vec3 f0 = surfaceF0(g1.rgb, metallic);
|
|
||||||
float dotNV = max(dot(n, v), 0.0);
|
|
||||||
|
|
||||||
#ifdef _gbuffer2
|
|
||||||
vec4 g2 = textureLod(gbuffer2, uv, 0.0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _MicroShadowing
|
|
||||||
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _Brdf
|
|
||||||
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
|
|
||||||
vec3 F = f0 * envBRDF.x + envBRDF.y;
|
|
||||||
#else
|
|
||||||
vec3 F = f0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Envmap
|
|
||||||
#ifdef _Irr
|
|
||||||
vec4 shPacked[7];
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
int base = i * 4;
|
|
||||||
shPacked[i] = vec4(
|
|
||||||
shirr[base],
|
|
||||||
shirr[base + 1],
|
|
||||||
shirr[base + 2],
|
|
||||||
shirr[base + 3]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
vec3 envl = shIrradiance(n, shPacked);
|
|
||||||
|
|
||||||
#ifdef _gbuffer2
|
|
||||||
if (g2.b < 0.5) {
|
|
||||||
envl = envl;
|
|
||||||
} else {
|
|
||||||
envl = vec3(0.0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _EnvTex
|
|
||||||
envl /= PI;
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
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;
|
|
||||||
|
|
||||||
#ifdef _Brdf
|
|
||||||
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;
|
|
||||||
|
|
||||||
vec4 trace = traceDiffuse(P, n, voxels, clipmaps);
|
|
||||||
vec3 color = trace.rgb * albedo * (1.0 - F);
|
|
||||||
color += envl * (1.0 - trace.a);
|
|
||||||
|
|
||||||
imageStore(voxels_diffuse, ivec2(pixel), vec4(color, 1.0));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,6 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
|
|||||||
#include "std/gbuffer.glsl"
|
#include "std/gbuffer.glsl"
|
||||||
#include "std/imageatomic.glsl"
|
#include "std/imageatomic.glsl"
|
||||||
#include "std/conetrace.glsl"
|
#include "std/conetrace.glsl"
|
||||||
#include "std/brdf.glsl"
|
|
||||||
|
|
||||||
uniform sampler2D gbufferD;
|
uniform sampler2D gbufferD;
|
||||||
uniform sampler2D gbuffer0;
|
uniform sampler2D gbuffer0;
|
||||||
@ -39,7 +38,9 @@ uniform layout(rgba8) image2D voxels_specular;
|
|||||||
|
|
||||||
uniform float clipmaps[voxelgiClipmapCount * 10];
|
uniform float clipmaps[voxelgiClipmapCount * 10];
|
||||||
uniform mat4 InvVP;
|
uniform mat4 InvVP;
|
||||||
|
uniform vec2 cameraProj;
|
||||||
uniform vec3 eye;
|
uniform vec3 eye;
|
||||||
|
uniform vec3 eyeLook;
|
||||||
uniform vec2 postprocess_resolution;
|
uniform vec2 postprocess_resolution;
|
||||||
uniform sampler2D sveloc;
|
uniform sampler2D sveloc;
|
||||||
|
|
||||||
@ -55,10 +56,12 @@ void main() {
|
|||||||
|
|
||||||
float x = uv.x * 2 - 1;
|
float x = uv.x * 2 - 1;
|
||||||
float y = uv.y * 2 - 1;
|
float y = uv.y * 2 - 1;
|
||||||
vec4 clipPos = vec4(x, y, depth, 1.0);
|
vec4 v = vec4(x, y, 1.0, 1.0);
|
||||||
vec4 worldPos = InvVP * clipPos;
|
v = vec4(InvVP * v);
|
||||||
vec3 P = worldPos.xyz / worldPos.w;
|
v.xyz /= v.w;
|
||||||
|
|
||||||
|
vec3 viewRay = v.xyz - eye;
|
||||||
|
vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
|
||||||
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
|
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
|
||||||
|
|
||||||
vec3 n;
|
vec3 n;
|
||||||
@ -68,7 +71,7 @@ void main() {
|
|||||||
|
|
||||||
vec2 velocity = -textureLod(sveloc, uv, 0.0).rg;
|
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, normalize(eye - P), g0.z, clipmaps, pixel, velocity).rgb;
|
||||||
|
|
||||||
imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0));
|
imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,8 +23,8 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
#include "compiled.inc"
|
#include "compiled.inc"
|
||||||
|
|
||||||
uniform layout(r8) image3D input_sdf;
|
uniform layout(r16) image3D input_sdf;
|
||||||
uniform layout(r8) image3D output_sdf;
|
uniform layout(r16) image3D output_sdf;
|
||||||
|
|
||||||
uniform float jump_size;
|
uniform float jump_size;
|
||||||
uniform int clipmapLevel;
|
uniform int clipmapLevel;
|
||||||
|
|||||||
@ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels;
|
|||||||
uniform layout(r32ui) uimage3D voxelsLight;
|
uniform layout(r32ui) uimage3D voxelsLight;
|
||||||
uniform layout(rgba8) image3D voxelsB;
|
uniform layout(rgba8) image3D voxelsB;
|
||||||
uniform layout(rgba8) image3D voxelsOut;
|
uniform layout(rgba8) image3D voxelsOut;
|
||||||
uniform layout(r8) image3D SDF;
|
uniform layout(r16) image3D SDF;
|
||||||
#else
|
#else
|
||||||
#ifdef _VoxelAOvar
|
#ifdef _VoxelAOvar
|
||||||
#ifdef _VoxelShadow
|
#ifdef _VoxelShadow
|
||||||
uniform layout(r8) image3D SDF;
|
uniform layout(r16) image3D SDF;
|
||||||
#endif
|
#endif
|
||||||
uniform layout(r32ui) uimage3D voxels;
|
uniform layout(r32ui) uimage3D voxels;
|
||||||
uniform layout(r8) image3D voxelsB;
|
uniform layout(r16) image3D voxelsB;
|
||||||
uniform layout(r8) image3D voxelsOut;
|
uniform layout(r16) image3D voxelsOut;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -74,9 +74,14 @@ void main() {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int nor_count = 0;
|
ivec3 src = ivec3(gl_GlobalInvocationID.xyz);
|
||||||
vec3 avgNormal = vec3(0.0);
|
#ifdef _VoxelGI
|
||||||
mat3 TBN = mat3(0.0);
|
vec3 light = vec3(0.0);
|
||||||
|
light.r = float(imageLoad(voxelsLight, src)) / 255;
|
||||||
|
light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255;
|
||||||
|
light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255;
|
||||||
|
light /= 3;
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++)
|
for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++)
|
||||||
{
|
{
|
||||||
@ -86,7 +91,7 @@ void main() {
|
|||||||
float aniso_colors[6];
|
float aniso_colors[6];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ivec3 src = ivec3(gl_GlobalInvocationID.xyz);
|
src = ivec3(gl_GlobalInvocationID.xyz);
|
||||||
src.x += i * res;
|
src.x += i * res;
|
||||||
ivec3 dst = src;
|
ivec3 dst = src;
|
||||||
dst.y += clipmapLevel * res;
|
dst.y += clipmapLevel * res;
|
||||||
@ -99,47 +104,28 @@ void main() {
|
|||||||
|
|
||||||
if (i < 6) {
|
if (i < 6) {
|
||||||
#ifdef _VoxelGI
|
#ifdef _VoxelGI
|
||||||
int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15)));
|
|
||||||
if (count > 0) {
|
|
||||||
vec4 basecol = vec4(0.0);
|
vec4 basecol = vec4(0.0);
|
||||||
basecol.r = float(imageLoad(voxels, src)) / 255;
|
basecol.r = float(imageLoad(voxels, src)) / 255;
|
||||||
basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 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.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.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255;
|
||||||
basecol /= count;
|
basecol /= 4;
|
||||||
vec3 emission = vec3(0.0);
|
vec3 emission = vec3(0.0);
|
||||||
emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255;
|
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.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.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255;
|
||||||
emission /= count;
|
emission /= 3;
|
||||||
vec3 N = vec3(0.0);
|
vec3 N = vec3(0.0);
|
||||||
N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255;
|
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.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255;
|
||||||
N /= count;
|
N /= 2;
|
||||||
N = decode_oct(N.rg * 2.0 - 1.0);
|
vec3 wnormal = decode_oct(N.rg * 2 - 1);
|
||||||
|
|
||||||
if (abs(N.x) > 0)
|
|
||||||
avgNormal.x += N.x;
|
|
||||||
if (abs(N.y) > 0)
|
|
||||||
avgNormal.y += N.y;
|
|
||||||
if (abs(N.z) > 0)
|
|
||||||
avgNormal.z += N.z;
|
|
||||||
if (i == 5)
|
|
||||||
{
|
|
||||||
avgNormal = normalize(avgNormal);
|
|
||||||
TBN = makeTangentBasis(avgNormal);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 envl = vec3(0.0);
|
vec3 envl = vec3(0.0);
|
||||||
envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255;
|
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.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.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255;
|
||||||
envl /= count;
|
envl /= 3;
|
||||||
vec3 light = vec3(0.0);
|
envl *= 100;
|
||||||
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
|
//clipmap to world
|
||||||
vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x;
|
vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x;
|
||||||
@ -149,17 +135,13 @@ void main() {
|
|||||||
wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]);
|
wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]);
|
||||||
|
|
||||||
radiance = basecol;
|
radiance = basecol;
|
||||||
vec4 trace = traceDiffuse(wposition, N, voxelsSampler, clipmaps);
|
vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps);
|
||||||
vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a);
|
vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a);
|
||||||
radiance.rgb *= light + indirect;
|
radiance.rgb *= light + indirect;
|
||||||
radiance.rgb += emission.rgb;
|
radiance.rgb += emission.rgb;
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x)));
|
|
||||||
if (count > 0) {
|
|
||||||
opac = float(imageLoad(voxels, src)) / 255;
|
opac = float(imageLoad(voxels, src)) / 255;
|
||||||
opac /= count;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _VoxelGI
|
#ifdef _VoxelGI
|
||||||
@ -213,7 +195,7 @@ void main() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// precompute cone sampling:
|
// precompute cone sampling:
|
||||||
vec3 coneDirection = TBN * DIFFUSE_CONE_DIRECTIONS[i - 6];
|
vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6];
|
||||||
vec3 aniso_direction = -coneDirection;
|
vec3 aniso_direction = -coneDirection;
|
||||||
uvec3 face_offsets = uvec3(
|
uvec3 face_offsets = uvec3(
|
||||||
aniso_direction.x > 0 ? 0 : 1,
|
aniso_direction.x > 0 ? 0 : 1,
|
||||||
|
|||||||
@ -12,7 +12,6 @@ class App {
|
|||||||
static var traitInits: Array<Void->Void> = [];
|
static var traitInits: Array<Void->Void> = [];
|
||||||
static var traitUpdates: Array<Void->Void> = [];
|
static var traitUpdates: Array<Void->Void> = [];
|
||||||
static var traitLateUpdates: Array<Void->Void> = [];
|
static var traitLateUpdates: Array<Void->Void> = [];
|
||||||
static var traitFixedUpdates: Array<Void->Void> = [];
|
|
||||||
static var traitRenders: Array<kha.graphics4.Graphics->Void> = [];
|
static var traitRenders: Array<kha.graphics4.Graphics->Void> = [];
|
||||||
static var traitRenders2D: Array<kha.graphics2.Graphics->Void> = [];
|
static var traitRenders2D: Array<kha.graphics2.Graphics->Void> = [];
|
||||||
public static var framebuffer: kha.Framebuffer;
|
public static var framebuffer: kha.Framebuffer;
|
||||||
@ -24,8 +23,6 @@ class App {
|
|||||||
public static var renderPathTime: Float;
|
public static var renderPathTime: Float;
|
||||||
public static var endFrameCallbacks: Array<Void->Void> = [];
|
public static var endFrameCallbacks: Array<Void->Void> = [];
|
||||||
#end
|
#end
|
||||||
static var last = 0.0;
|
|
||||||
static var time = 0.0;
|
|
||||||
static var lastw = -1;
|
static var lastw = -1;
|
||||||
static var lasth = -1;
|
static var lasth = -1;
|
||||||
public static var onResize: Void->Void = null;
|
public static var onResize: Void->Void = null;
|
||||||
@ -37,14 +34,13 @@ class App {
|
|||||||
function new(done: Void->Void) {
|
function new(done: Void->Void) {
|
||||||
done();
|
done();
|
||||||
kha.System.notifyOnFrames(render);
|
kha.System.notifyOnFrames(render);
|
||||||
kha.Scheduler.addTimeTask(update, 0, iron.system.Time.step);
|
kha.Scheduler.addTimeTask(update, 0, iron.system.Time.delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function reset() {
|
public static function reset() {
|
||||||
traitInits = [];
|
traitInits = [];
|
||||||
traitUpdates = [];
|
traitUpdates = [];
|
||||||
traitLateUpdates = [];
|
traitLateUpdates = [];
|
||||||
traitFixedUpdates = [];
|
|
||||||
traitRenders = [];
|
traitRenders = [];
|
||||||
traitRenders2D = [];
|
traitRenders2D = [];
|
||||||
if (onResets != null) for (f in onResets) f();
|
if (onResets != null) for (f in onResets) f();
|
||||||
@ -52,39 +48,6 @@ class App {
|
|||||||
|
|
||||||
static function update() {
|
static function update() {
|
||||||
if (Scene.active == null || !Scene.active.ready) return;
|
if (Scene.active == null || !Scene.active.ready) return;
|
||||||
|
|
||||||
// VR is handling it so we prevent double updates
|
|
||||||
// TODO: avoid js.Syntax
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
var vrActive = false;
|
|
||||||
js.Syntax.code("
|
|
||||||
if (typeof kha !== 'undefined' && kha.vr && kha.vr.VrInterface) {
|
|
||||||
const vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr && vr.IsPresenting && vr.IsPresenting()) {
|
|
||||||
{0} = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
", vrActive);
|
|
||||||
if (vrActive) return;
|
|
||||||
#end
|
|
||||||
|
|
||||||
iron.system.Time.update();
|
|
||||||
|
|
||||||
if (lastw == -1) {
|
|
||||||
lastw = App.w();
|
|
||||||
lasth = App.h();
|
|
||||||
}
|
|
||||||
if (lastw != App.w() || lasth != App.h()) {
|
|
||||||
if (onResize != null) onResize();
|
|
||||||
else {
|
|
||||||
if (Scene.active != null && Scene.active.camera != null) {
|
|
||||||
Scene.active.camera.buildProjection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastw = App.w();
|
|
||||||
lasth = App.h();
|
|
||||||
|
|
||||||
if (pauseUpdates) return;
|
if (pauseUpdates) return;
|
||||||
|
|
||||||
#if lnx_debug
|
#if lnx_debug
|
||||||
@ -93,14 +56,6 @@ class App {
|
|||||||
|
|
||||||
Scene.active.updateFrame();
|
Scene.active.updateFrame();
|
||||||
|
|
||||||
|
|
||||||
time += iron.system.Time.delta;
|
|
||||||
|
|
||||||
while (time >= iron.system.Time.fixedStep) {
|
|
||||||
for (f in traitFixedUpdates) f();
|
|
||||||
time -= iron.system.Time.fixedStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var l = traitUpdates.length;
|
var l = traitUpdates.length;
|
||||||
while (i < l) {
|
while (i < l) {
|
||||||
@ -129,13 +84,29 @@ class App {
|
|||||||
for (cb in endFrameCallbacks) cb();
|
for (cb in endFrameCallbacks) cb();
|
||||||
updateTime = kha.Scheduler.realTime() - startTime;
|
updateTime = kha.Scheduler.realTime() - startTime;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
// Rebuild projection on window resize
|
||||||
|
if (lastw == -1) {
|
||||||
|
lastw = App.w();
|
||||||
|
lasth = App.h();
|
||||||
|
}
|
||||||
|
if (lastw != App.w() || lasth != App.h()) {
|
||||||
|
if (onResize != null) onResize();
|
||||||
|
else {
|
||||||
|
if (Scene.active != null && Scene.active.camera != null) {
|
||||||
|
Scene.active.camera.buildProjection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastw = App.w();
|
||||||
|
lasth = App.h();
|
||||||
}
|
}
|
||||||
|
|
||||||
static function render(frames: Array<kha.Framebuffer>) {
|
static function render(frames: Array<kha.Framebuffer>) {
|
||||||
var frame = frames[0];
|
var frame = frames[0];
|
||||||
framebuffer = frame;
|
framebuffer = frame;
|
||||||
|
|
||||||
iron.system.Time.render();
|
iron.system.Time.update();
|
||||||
|
|
||||||
if (Scene.active == null || !Scene.active.ready) {
|
if (Scene.active == null || !Scene.active.ready) {
|
||||||
render2D(frame);
|
render2D(frame);
|
||||||
@ -153,21 +124,6 @@ class App {
|
|||||||
traitInits.splice(0, traitInits.length);
|
traitInits.splice(0, traitInits.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip for XR callback to handle rendering
|
|
||||||
// TODO: avoid js Syntax
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
var vrActive = false;
|
|
||||||
js.Syntax.code("
|
|
||||||
if (typeof kha !== 'undefined' && kha.vr && kha.vr.VrInterface) {
|
|
||||||
const vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr && vr.IsPresenting && vr.IsPresenting()) {
|
|
||||||
{0} = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
", vrActive);
|
|
||||||
|
|
||||||
if (!vrActive) {
|
|
||||||
#end
|
|
||||||
Scene.active.renderFrame(frame.g4);
|
Scene.active.renderFrame(frame.g4);
|
||||||
|
|
||||||
for (f in traitRenders) {
|
for (f in traitRenders) {
|
||||||
@ -176,10 +132,6 @@ class App {
|
|||||||
|
|
||||||
render2D(frame);
|
render2D(frame);
|
||||||
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
#if lnx_debug
|
#if lnx_debug
|
||||||
renderPathTime = kha.Scheduler.realTime() - startTime;
|
renderPathTime = kha.Scheduler.realTime() - startTime;
|
||||||
#end
|
#end
|
||||||
@ -220,14 +172,6 @@ class App {
|
|||||||
traitLateUpdates.remove(f);
|
traitLateUpdates.remove(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function notifyOnFixedUpdate(f: Void->Void) {
|
|
||||||
traitFixedUpdates.push(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function removeFixedUpdate(f: Void->Void) {
|
|
||||||
traitFixedUpdates.remove(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function notifyOnRender(f: kha.graphics4.Graphics->Void) {
|
public static function notifyOnRender(f: kha.graphics4.Graphics->Void) {
|
||||||
traitRenders.push(f);
|
traitRenders.push(f);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,44 +18,10 @@ import iron.object.LightObject;
|
|||||||
import iron.object.MeshObject;
|
import iron.object.MeshObject;
|
||||||
import iron.object.Uniforms;
|
import iron.object.Uniforms;
|
||||||
import iron.object.Clipmap;
|
import iron.object.Clipmap;
|
||||||
#if lnx_vr
|
|
||||||
import iron.math.Vec4;
|
|
||||||
import iron.math.Mat4;
|
|
||||||
import iron.math.Quat;
|
|
||||||
#end
|
|
||||||
|
|
||||||
class RenderPath {
|
class RenderPath {
|
||||||
|
|
||||||
public static var active: RenderPath;
|
public static var active: RenderPath;
|
||||||
#if lnx_vr
|
|
||||||
static var vrSimulateMode: Bool = false;
|
|
||||||
static var vrCameraOffsetSet:Bool = false;
|
|
||||||
static var vrCameraOffset:Vec4 = new Vec4();
|
|
||||||
static var wasVRPresenting:Bool = false;
|
|
||||||
public static var vrCalibrationPosition:Vec4 = null;
|
|
||||||
public static var vrCalibrationRotation:iron.math.Quat = null;
|
|
||||||
public static var vrCalibrationSaved:Bool = false;
|
|
||||||
|
|
||||||
public static var vrCenterCameraWorld:Mat4 = null;
|
|
||||||
|
|
||||||
static var vrOriginalSuperSample:Float = -1.0;
|
|
||||||
public static inline function isVRPresenting(): Bool {
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
return kha.vr.VrInterface.instance != null && kha.vr.VrInterface.instance.IsPresenting();
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
|
|
||||||
public static inline function isVRSimulateMode(): Bool {
|
|
||||||
return vrSimulateMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: done remove safely
|
|
||||||
public static inline function debugLog(msg: String, once: Bool = true): Void {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
public var frameScissor = false;
|
public var frameScissor = false;
|
||||||
public var frameScissorX = 0;
|
public var frameScissorX = 0;
|
||||||
@ -77,13 +43,9 @@ class RenderPath {
|
|||||||
public var isProbe = false;
|
public var isProbe = false;
|
||||||
public var currentG: Graphics = null;
|
public var currentG: Graphics = null;
|
||||||
public var frameG: Graphics;
|
public var frameG: Graphics;
|
||||||
#if lnx_vr
|
|
||||||
var beginCalled = false;
|
|
||||||
var renderToXRFramebuffer = false;
|
|
||||||
#end
|
|
||||||
public var drawOrder = DrawOrder.Distance;
|
public var drawOrder = DrawOrder.Distance;
|
||||||
public var paused = false;
|
public var paused = false;
|
||||||
public var ready(get, never): Bool;
|
public var ready(get, null): Bool;
|
||||||
function get_ready(): Bool { return loading == 0; }
|
function get_ready(): Bool { return loading == 0; }
|
||||||
public var commands: Void->Void = null;
|
public var commands: Void->Void = null;
|
||||||
public var setupDepthTexture: Void->Void = null;
|
public var setupDepthTexture: Void->Void = null;
|
||||||
@ -161,93 +123,9 @@ class RenderPath {
|
|||||||
public function renderFrame(g: Graphics) {
|
public function renderFrame(g: Graphics) {
|
||||||
if (!ready || paused || iron.App.w() == 0 || iron.App.h() == 0) return;
|
if (!ready || paused || iron.App.w() == 0 || iron.App.h() == 0) return;
|
||||||
|
|
||||||
var appW = iron.App.w();
|
if (lastW > 0 && (lastW != iron.App.w() || lastH != iron.App.h())) resize();
|
||||||
var appH = iron.App.h();
|
lastW = iron.App.w();
|
||||||
|
lastH = iron.App.h();
|
||||||
// use native XR framebuffer dimensions
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
if (kha.vr.VrInterface.instance != null) {
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
var isPresenting = vr != null && vr.IsPresenting();
|
|
||||||
|
|
||||||
// save/restore camera position between modes
|
|
||||||
if (!wasVRPresenting && isPresenting) {
|
|
||||||
if (Scene.active != null && Scene.active.camera != null) {
|
|
||||||
if (vrCalibrationPosition == null) vrCalibrationPosition = new Vec4();
|
|
||||||
if (vrCalibrationRotation == null) vrCalibrationRotation = new Quat();
|
|
||||||
|
|
||||||
vrCalibrationPosition.setFrom(Scene.active.camera.transform.loc);
|
|
||||||
vrCalibrationRotation.setFrom(Scene.active.camera.transform.rot);
|
|
||||||
vrCalibrationSaved = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save original super sampling for later
|
|
||||||
vrOriginalSuperSample = leenkx.renderpath.Inc.superSample;
|
|
||||||
|
|
||||||
// compositeToXR function handles blitting to VR framebuffer
|
|
||||||
|
|
||||||
var xrVr: kha.js.vr.VrInterface = cast vr;
|
|
||||||
if (xrVr.xrGLLayer != null) {
|
|
||||||
var vrWidth = untyped xrVr.xrGLLayer.framebufferWidth;
|
|
||||||
var vrHeight = untyped xrVr.xrGLLayer.framebufferHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (wasVRPresenting && !isPresenting) {
|
|
||||||
// reset VR frame time before anything else
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
iron.system.Time.vrFrameTime = -1.0;
|
|
||||||
#end
|
|
||||||
|
|
||||||
if (vrCalibrationSaved && Scene.active != null && Scene.active.camera != null) {
|
|
||||||
Scene.active.camera.transform.loc.setFrom(vrCalibrationPosition);
|
|
||||||
Scene.active.camera.transform.rot.setFrom(vrCalibrationRotation);
|
|
||||||
Scene.active.camera.buildMatrix();
|
|
||||||
Scene.active.camera.buildProjection();
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore original super sampling from simulate mode
|
|
||||||
if (vrOriginalSuperSample >= 0.0) {
|
|
||||||
leenkx.renderpath.Inc.superSample = vrOriginalSuperSample;
|
|
||||||
|
|
||||||
for (rt in renderTargets) {
|
|
||||||
if (rt.raw.width == 0 && rt.raw.scale != null) {
|
|
||||||
rt.raw.scale = vrOriginalSuperSample;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resize();
|
|
||||||
vrOriginalSuperSample = -1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset offset for next session
|
|
||||||
vrCameraOffsetSet = false;
|
|
||||||
vrCameraOffset = null;
|
|
||||||
}
|
|
||||||
wasVRPresenting = isPresenting;
|
|
||||||
|
|
||||||
if (isPresenting) {
|
|
||||||
// TODO: re-investigate using super sampling to avoid pixelation in simulate mode while giving max quality in headset
|
|
||||||
if (vrOriginalSuperSample >= 0.0 && leenkx.renderpath.Inc.superSample != 4.0) {
|
|
||||||
leenkx.renderpath.Inc.superSample = 4.0;
|
|
||||||
for (rt in renderTargets) {
|
|
||||||
if (rt.raw.width == 0 && rt.raw.scale != null) {
|
|
||||||
rt.raw.scale = 4.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resize();
|
|
||||||
}
|
|
||||||
|
|
||||||
var xrVr: kha.js.vr.VrInterface = cast vr;
|
|
||||||
if (xrVr.xrGLLayer != null) {
|
|
||||||
appW = xrVr.xrGLLayer.framebufferWidth;
|
|
||||||
appH = xrVr.xrGLLayer.framebufferHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
if (lastW > 0 && (lastW != appW || lastH != appH)) resize();
|
|
||||||
lastW = appW;
|
|
||||||
lastH = appH;
|
|
||||||
|
|
||||||
frameTime = Time.time() - lastFrameTime;
|
frameTime = Time.time() - lastFrameTime;
|
||||||
lastFrameTime = Time.time();
|
lastFrameTime = Time.time();
|
||||||
@ -313,9 +191,7 @@ class RenderPath {
|
|||||||
}
|
}
|
||||||
light = Scene.active.lights[0];
|
light = Scene.active.lights[0];
|
||||||
|
|
||||||
if (commands != null) {
|
|
||||||
commands();
|
commands();
|
||||||
}
|
|
||||||
|
|
||||||
if (!isProbe) frame++;
|
if (!isProbe) frame++;
|
||||||
}
|
}
|
||||||
@ -331,13 +207,13 @@ class RenderPath {
|
|||||||
begin(frameG, Scene.active.camera.currentFace);
|
begin(frameG, Scene.active.camera.currentFace);
|
||||||
}
|
}
|
||||||
else { // Screen, planar probe
|
else { // Screen, planar probe
|
||||||
currentW = kha.System.windowWidth();
|
currentW = iron.App.w();
|
||||||
currentH = kha.System.windowHeight();
|
currentH = iron.App.h();
|
||||||
if (frameScissor) setFrameScissor();
|
if (frameScissor) setFrameScissor();
|
||||||
begin(frameG);
|
begin(frameG);
|
||||||
if (!isProbe) {
|
if (!isProbe) {
|
||||||
setCurrentViewport(kha.System.windowWidth(), kha.System.windowHeight());
|
setCurrentViewport(iron.App.w(), iron.App.h());
|
||||||
setCurrentScissor(kha.System.windowWidth(), kha.System.windowHeight());
|
setCurrentScissor(iron.App.w(), iron.App.h());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -382,42 +258,16 @@ class RenderPath {
|
|||||||
if (currentG != null) end();
|
if (currentG != null) end();
|
||||||
currentG = g;
|
currentG = g;
|
||||||
additionalTargets = additionalRenderTargets;
|
additionalTargets = additionalRenderTargets;
|
||||||
|
|
||||||
// we still bind but skip begin() when explicitly rendering to XR framebuffer (renderToXRFramebuffer flag)
|
|
||||||
#if lnx_vr
|
|
||||||
if (!renderToXRFramebuffer) {
|
|
||||||
face >= 0 ? g.beginFace(face) : g.begin(additionalRenderTargets);
|
face >= 0 ? g.beginFace(face) : g.begin(additionalRenderTargets);
|
||||||
beginCalled = true;
|
|
||||||
} else {
|
|
||||||
// XR framebuffer is already bound by VrInterface so we dont rebind
|
|
||||||
beginCalled = false;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
face >= 0 ? g.beginFace(face) : g.begin(additionalRenderTargets);
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline function end() {
|
inline function end() {
|
||||||
if (currentG == null) return;
|
|
||||||
if (scissorSet) {
|
if (scissorSet) {
|
||||||
currentG.disableScissor();
|
currentG.disableScissor();
|
||||||
scissorSet = false;
|
scissorSet = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if lnx_vr
|
|
||||||
if (beginCalled) {
|
|
||||||
currentG.end();
|
|
||||||
beginCalled = false;
|
|
||||||
}
|
|
||||||
// persist for rendering both eyes
|
|
||||||
if (!isVRPresenting()) {
|
|
||||||
currentG = null;
|
|
||||||
additionalTargets = null;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
currentG.end();
|
currentG.end();
|
||||||
currentG = null;
|
currentG = null;
|
||||||
#end
|
|
||||||
bindParams = null;
|
bindParams = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,17 +331,14 @@ class RenderPath {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function sortMeshesIndex(meshes: Array<MeshObject>) {
|
public static function sortMeshesShader(meshes: Array<MeshObject>) {
|
||||||
meshes.sort(function(a, b): Int {
|
meshes.sort(function(a, b): Int {
|
||||||
#if rp_depth_texture
|
#if rp_depth_texture
|
||||||
var depthDiff = boolToInt(a.depthRead) - boolToInt(b.depthRead);
|
var depthDiff = boolToInt(a.depthRead) - boolToInt(b.depthRead);
|
||||||
if (depthDiff != 0) return depthDiff;
|
if (depthDiff != 0) return depthDiff;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
if (a.data.sortingIndex != b.data.sortingIndex) {
|
return a.materials[0].name >= b.materials[0].name ? 1 : -1;
|
||||||
return a.data.sortingIndex > b.data.sortingIndex ? 1 : -1;
|
|
||||||
}
|
|
||||||
return a.data.name >= b.data.name ? 1 : -1;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,7 +399,7 @@ class RenderPath {
|
|||||||
#if lnx_batch
|
#if lnx_batch
|
||||||
sortMeshesDistance(Scene.active.meshBatch.nonBatched);
|
sortMeshesDistance(Scene.active.meshBatch.nonBatched);
|
||||||
#else
|
#else
|
||||||
drawOrder == DrawOrder.Index ? sortMeshesIndex(meshes) : sortMeshesDistance(meshes);
|
drawOrder == DrawOrder.Shader ? sortMeshesShader(meshes) : sortMeshesDistance(meshes);
|
||||||
#end
|
#end
|
||||||
meshesSorted = true;
|
meshesSorted = true;
|
||||||
}
|
}
|
||||||
@ -671,208 +518,12 @@ class RenderPath {
|
|||||||
return Reflect.field(kha.Shaders, handle + "_comp");
|
return Reflect.field(kha.Shaders, handle + "_comp");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if lnx_vr
|
#if (kha_krom && lnx_vr)
|
||||||
// blits to each eyes viewport in the XR framebuffer.
|
public function drawStereo(drawMeshes: Int->Void) {
|
||||||
public function compositeToXR(sourceTarget: String) {
|
for (eye in 0...2) {
|
||||||
#if (kha_webgl && lnx_vr)
|
Krom.vrBeginRender(eye);
|
||||||
|
drawMeshes(eye);
|
||||||
var vr: kha.js.vr.VrInterface = cast kha.vr.VrInterface.instance;
|
Krom.vrEndRender(eye);
|
||||||
if (vr == null || vr._glContext == null || vr.xrGLLayer == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var gl: js.html.webgl.WebGL2RenderingContext = cast vr._glContext;
|
|
||||||
var source = renderTargets.get(sourceTarget);
|
|
||||||
if (source == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var sourceFB: js.html.webgl.Framebuffer = untyped source.image.g4.renderTargetFrameBuffer;
|
|
||||||
if (sourceFB == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// trace('Framebuffer OK');
|
|
||||||
|
|
||||||
renderToXRFramebuffer = true;
|
|
||||||
gl.bindFramebuffer(js.html.webgl.WebGL2RenderingContext.DRAW_FRAMEBUFFER, vr.xrGLLayer.framebuffer);
|
|
||||||
gl.bindFramebuffer(js.html.webgl.WebGL2RenderingContext.READ_FRAMEBUFFER, sourceFB);
|
|
||||||
|
|
||||||
var readStatus = gl.checkFramebufferStatus(js.html.webgl.WebGL2RenderingContext.READ_FRAMEBUFFER);
|
|
||||||
var drawStatus = gl.checkFramebufferStatus(js.html.webgl.WebGL2RenderingContext.DRAW_FRAMEBUFFER);
|
|
||||||
if (readStatus != js.html.webgl.WebGL2RenderingContext.FRAMEBUFFER_COMPLETE ||
|
|
||||||
drawStatus != js.html.webgl.WebGL2RenderingContext.FRAMEBUFFER_COMPLETE) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var halfWidth = Std.int(source.image.width / 2);
|
|
||||||
var fullHeight = source.image.height;
|
|
||||||
|
|
||||||
if (vr._leftViewport != null) {
|
|
||||||
var vp = vr._leftViewport;
|
|
||||||
gl.blitFramebuffer(
|
|
||||||
0, 0, halfWidth, fullHeight,
|
|
||||||
vp.x, vp.y, vp.x + vp.width, vp.y + vp.height,
|
|
||||||
js.html.webgl.WebGL2RenderingContext.COLOR_BUFFER_BIT,
|
|
||||||
js.html.webgl.WebGL2RenderingContext.LINEAR
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (vr._rightViewport != null) {
|
|
||||||
var vp = vr._rightViewport;
|
|
||||||
gl.blitFramebuffer(
|
|
||||||
halfWidth, 0, source.image.width, fullHeight,
|
|
||||||
vp.x, vp.y, vp.x + vp.width, vp.y + vp.height,
|
|
||||||
js.html.webgl.WebGL2RenderingContext.COLOR_BUFFER_BIT,
|
|
||||||
js.html.webgl.WebGL2RenderingContext.LINEAR
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.bindFramebuffer(js.html.webgl.WebGL2RenderingContext.FRAMEBUFFER, null);
|
|
||||||
renderToXRFramebuffer = false;
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
#if lnx_vr
|
|
||||||
public function drawStereo(drawMeshes: Void->Void) {
|
|
||||||
vrSimulateMode = false;
|
|
||||||
|
|
||||||
if (currentG == null && frameG != null) {
|
|
||||||
currentG = frameG;
|
|
||||||
}
|
|
||||||
|
|
||||||
var appw = iron.App.w();
|
|
||||||
var apph = iron.App.h();
|
|
||||||
var g = currentG;
|
|
||||||
|
|
||||||
// get render target dimensions not App.w/h gbuffer is scaled in simulate mode with supersampling
|
|
||||||
|
|
||||||
var gbuffer0 = renderTargets.get("gbuffer0");
|
|
||||||
var actualWidth = (gbuffer0 != null && gbuffer0.image != null) ? gbuffer0.image.width : appw;
|
|
||||||
var actualHeight = (gbuffer0 != null && gbuffer0.image != null) ? gbuffer0.image.height : apph;
|
|
||||||
var actualHalfWidth = Std.int(actualWidth / 2);
|
|
||||||
|
|
||||||
var vrFBWidth = actualWidth;
|
|
||||||
var vrFBHeight = actualHeight;
|
|
||||||
var vrHalfWidth = actualHalfWidth;
|
|
||||||
var isVRPresenting = false;
|
|
||||||
vrSimulateMode = false;
|
|
||||||
|
|
||||||
var vr:Dynamic = null;
|
|
||||||
var vrExists = false;
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
if (kha.vr.VrInterface.instance != null) {
|
|
||||||
vr = kha.vr.VrInterface.instance;
|
|
||||||
vrExists = true;
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
if (vrExists && vr != null && vr.IsPresenting()) {
|
|
||||||
vrSimulateMode = false;
|
|
||||||
isVRPresenting = true;
|
|
||||||
|
|
||||||
// get framebuffer dimensions from XR layer
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
var xrVr: kha.js.vr.VrInterface = cast vr;
|
|
||||||
if (xrVr.xrGLLayer != null) {
|
|
||||||
vrFBWidth = untyped xrVr.xrGLLayer.framebufferWidth;
|
|
||||||
vrFBHeight = untyped xrVr.xrGLLayer.framebufferHeight;
|
|
||||||
vrHalfWidth = Std.int(vrFBWidth / 2);
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
if (Scene.active == null || Scene.active.camera == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
if (vrCenterCameraWorld == null) vrCenterCameraWorld = Mat4.identity();
|
|
||||||
vrCenterCameraWorld.setFrom(Scene.active.camera.transform.world);
|
|
||||||
#end
|
|
||||||
|
|
||||||
// LEFT EYE
|
|
||||||
// HMD center for room scale position tracking
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
var xrVr: kha.js.vr.VrInterface = cast vr;
|
|
||||||
if (xrVr.currentViewerPose != null) {
|
|
||||||
var viewerTransform = untyped xrVr.currentViewerPose.transform;
|
|
||||||
if (viewerTransform != null && viewerTransform.position != null) {
|
|
||||||
// VR present calibration is used to position objects in world space not the camera
|
|
||||||
var pos = viewerTransform.position;
|
|
||||||
|
|
||||||
// camera follows headset directly in local floor space
|
|
||||||
Scene.active.camera.transform.loc.set(pos.x, pos.y, pos.z);
|
|
||||||
|
|
||||||
if (viewerTransform.orientation != null) {
|
|
||||||
Scene.active.camera.transform.rot.set(
|
|
||||||
viewerTransform.orientation.x,
|
|
||||||
viewerTransform.orientation.y,
|
|
||||||
viewerTransform.orientation.z,
|
|
||||||
viewerTransform.orientation.w
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Scene.active.camera.transform.buildMatrix();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iron.system.VRController.updatePoses();
|
|
||||||
#end
|
|
||||||
|
|
||||||
Scene.active.camera.V.self = vr.GetViewMatrix(0);
|
|
||||||
Scene.active.camera.P.self = vr.GetProjectionMatrix(0);
|
|
||||||
Scene.active.camera.VP.setFrom(Scene.active.camera.P);
|
|
||||||
Scene.active.camera.VP.multmat(Scene.active.camera.V);
|
|
||||||
Scene.active.camera.buildMatrix(); // update frustum for culling
|
|
||||||
|
|
||||||
var renderWidth = actualWidth;
|
|
||||||
var renderHeight = actualHeight;
|
|
||||||
var renderHalfWidth = actualHalfWidth;
|
|
||||||
|
|
||||||
// left half of render target
|
|
||||||
g.viewport(0, 0, renderHalfWidth, renderHeight);
|
|
||||||
g.scissor(0, 0, renderHalfWidth, renderHeight);
|
|
||||||
drawMeshes();
|
|
||||||
|
|
||||||
// RIGHT EYE
|
|
||||||
Scene.active.camera.V.self = vr.GetViewMatrix(1);
|
|
||||||
Scene.active.camera.P.self = vr.GetProjectionMatrix(1);
|
|
||||||
Scene.active.camera.VP.setFrom(Scene.active.camera.P);
|
|
||||||
Scene.active.camera.VP.multmat(Scene.active.camera.V);
|
|
||||||
Scene.active.camera.buildMatrix();
|
|
||||||
|
|
||||||
// right half of render target
|
|
||||||
g.viewport(renderHalfWidth, 0, renderHalfWidth, renderHeight);
|
|
||||||
g.scissor(renderHalfWidth, 0, renderHalfWidth, renderHeight);
|
|
||||||
drawMeshes();
|
|
||||||
|
|
||||||
// restore for post-processing
|
|
||||||
g.disableScissor();
|
|
||||||
g.viewport(0, 0, renderWidth, renderHeight);
|
|
||||||
}
|
|
||||||
else { // Simulate
|
|
||||||
vrSimulateMode = true;
|
|
||||||
var ipd_offset = 0.032 * 35.0;
|
|
||||||
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
if (vrCenterCameraWorld == null) vrCenterCameraWorld = Mat4.identity();
|
|
||||||
vrCenterCameraWorld.setFrom(Scene.active.camera.transform.world);
|
|
||||||
#end
|
|
||||||
|
|
||||||
Scene.active.camera.buildProjection(actualHalfWidth / actualHeight);
|
|
||||||
|
|
||||||
Scene.active.camera.transform.move(Scene.active.camera.right(), -ipd_offset);
|
|
||||||
Scene.active.camera.buildMatrix();
|
|
||||||
g.viewport(0, 0, actualHalfWidth, actualHeight);
|
|
||||||
g.scissor(0, 0, actualHalfWidth, actualHeight);
|
|
||||||
drawMeshes();
|
|
||||||
|
|
||||||
begin(g, additionalTargets);
|
|
||||||
Scene.active.camera.transform.move(Scene.active.camera.right(), ipd_offset * 2.0);
|
|
||||||
Scene.active.camera.buildMatrix();
|
|
||||||
g.viewport(actualHalfWidth, 0, actualHalfWidth, actualHeight);
|
|
||||||
g.scissor(actualHalfWidth, 0, actualHalfWidth, actualHeight);
|
|
||||||
drawMeshes();
|
|
||||||
|
|
||||||
Scene.active.camera.transform.move(Scene.active.camera.right(), -ipd_offset);
|
|
||||||
Scene.active.camera.buildMatrix();
|
|
||||||
g.disableScissor();
|
|
||||||
g.viewport(0, 0, actualWidth, actualHeight);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
@ -1231,6 +882,6 @@ class CachedShaderContext {
|
|||||||
|
|
||||||
@:enum abstract DrawOrder(Int) from Int {
|
@:enum abstract DrawOrder(Int) from Int {
|
||||||
var Distance = 0; // Early-z
|
var Distance = 0; // Early-z
|
||||||
var Index = 1; // Less state changes
|
var Shader = 1; // Less state changes
|
||||||
// var Mix = 2; // Distance buckets sorted by shader
|
// var Mix = 2; // Distance buckets sorted by shader
|
||||||
}
|
}
|
||||||
|
|||||||
@ -775,7 +775,6 @@ class Scene {
|
|||||||
// Attach particle systems
|
// Attach particle systems
|
||||||
#if lnx_particles
|
#if lnx_particles
|
||||||
if (o.particle_refs != null) {
|
if (o.particle_refs != null) {
|
||||||
cast(object, MeshObject).render_emitter = o.render_emitter;
|
|
||||||
for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref);
|
for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref);
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
@ -783,11 +782,6 @@ class Scene {
|
|||||||
if (o.tilesheet_ref != null) {
|
if (o.tilesheet_ref != null) {
|
||||||
cast(object, MeshObject).setupTilesheet(sceneName, o.tilesheet_ref, o.tilesheet_action_ref);
|
cast(object, MeshObject).setupTilesheet(sceneName, o.tilesheet_ref, o.tilesheet_action_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o.camera_list != null){
|
|
||||||
cast(object, MeshObject).cameraList = o.camera_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
returnObject(object, o, done);
|
returnObject(object, o, done);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -887,12 +881,8 @@ class Scene {
|
|||||||
var ptype: String = t.props[i * 3 + 1];
|
var ptype: String = t.props[i * 3 + 1];
|
||||||
var pval: Dynamic = t.props[i * 3 + 2];
|
var pval: Dynamic = t.props[i * 3 + 2];
|
||||||
|
|
||||||
if (StringTools.endsWith(ptype, "Object") && pval != "" && pval != null) {
|
if (StringTools.endsWith(ptype, "Object") && pval != "") {
|
||||||
Reflect.setProperty(traitInst, pname, Scene.active.getChild(pval));
|
Reflect.setProperty(traitInst, pname, Scene.active.getChild(pval));
|
||||||
} else if (ptype == "TSceneFormat" && pval != "") {
|
|
||||||
Data.getSceneRaw(pval, function (r: TSceneFormat) {
|
|
||||||
Reflect.setProperty(traitInst, pname, r);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (ptype) {
|
switch (ptype) {
|
||||||
@ -954,14 +944,7 @@ class Scene {
|
|||||||
static function createTraitClassInstance(traitName: String, args: Array<Dynamic>): Dynamic {
|
static function createTraitClassInstance(traitName: String, args: Array<Dynamic>): Dynamic {
|
||||||
var cname = Type.resolveClass(traitName);
|
var cname = Type.resolveClass(traitName);
|
||||||
if (cname == null) return null;
|
if (cname == null) return null;
|
||||||
var trait:Dynamic;
|
return Type.createInstance(cname, args);
|
||||||
try {
|
|
||||||
trait = Type.createInstance(cname, args);
|
|
||||||
} catch(e) {
|
|
||||||
trace("Error creating trait: " + traitName + " - " + e);
|
|
||||||
trait = null;
|
|
||||||
}
|
|
||||||
return trait;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadEmbeddedData(datas: Array<String>, done: Void->Void) {
|
function loadEmbeddedData(datas: Array<String>, done: Void->Void) {
|
||||||
|
|||||||
@ -16,7 +16,6 @@ class Trait {
|
|||||||
var _remove: Array<Void->Void> = null;
|
var _remove: Array<Void->Void> = null;
|
||||||
var _update: Array<Void->Void> = null;
|
var _update: Array<Void->Void> = null;
|
||||||
var _lateUpdate: Array<Void->Void> = null;
|
var _lateUpdate: Array<Void->Void> = null;
|
||||||
var _fixedUpdate: Array<Void->Void> = null;
|
|
||||||
var _render: Array<kha.graphics4.Graphics->Void> = null;
|
var _render: Array<kha.graphics4.Graphics->Void> = null;
|
||||||
var _render2D: Array<kha.graphics2.Graphics->Void> = null;
|
var _render2D: Array<kha.graphics2.Graphics->Void> = null;
|
||||||
|
|
||||||
@ -88,23 +87,6 @@ class Trait {
|
|||||||
App.removeLateUpdate(f);
|
App.removeLateUpdate(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Add fixed game logic handler.
|
|
||||||
**/
|
|
||||||
public function notifyOnFixedUpdate(f: Void->Void) {
|
|
||||||
if (_fixedUpdate == null) _fixedUpdate = [];
|
|
||||||
_fixedUpdate.push(f);
|
|
||||||
App.notifyOnFixedUpdate(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Remove fixed game logic handler.
|
|
||||||
**/
|
|
||||||
public function removeFixedUpdate(f: Void->Void) {
|
|
||||||
_fixedUpdate.remove(f);
|
|
||||||
App.removeFixedUpdate(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Add render handler.
|
Add render handler.
|
||||||
**/
|
**/
|
||||||
|
|||||||
@ -37,9 +37,7 @@ class Armature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getAction(name: String): TAction {
|
public function getAction(name: String): TAction {
|
||||||
for (a in actions) {
|
for (a in actions) if (a.name == name) return a;
|
||||||
if (a.name == name) return a;
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import iron.data.SceneFormat;
|
|||||||
class MeshData {
|
class MeshData {
|
||||||
|
|
||||||
public var name: String;
|
public var name: String;
|
||||||
public var sortingIndex: Int;
|
|
||||||
public var raw: TMeshData;
|
public var raw: TMeshData;
|
||||||
public var format: TSceneFormat;
|
public var format: TSceneFormat;
|
||||||
public var geom: Geometry;
|
public var geom: Geometry;
|
||||||
@ -24,7 +23,6 @@ class MeshData {
|
|||||||
public function new(raw: TMeshData, done: MeshData->Void) {
|
public function new(raw: TMeshData, done: MeshData->Void) {
|
||||||
this.raw = raw;
|
this.raw = raw;
|
||||||
this.name = raw.name;
|
this.name = raw.name;
|
||||||
this.sortingIndex = raw.sorting_index;
|
|
||||||
|
|
||||||
if (raw.scale_pos != null) scalePos = raw.scale_pos;
|
if (raw.scale_pos != null) scalePos = raw.scale_pos;
|
||||||
if (raw.scale_tex != null) scaleTex = raw.scale_tex;
|
if (raw.scale_tex != null) scaleTex = raw.scale_tex;
|
||||||
|
|||||||
@ -49,7 +49,6 @@ typedef TMeshData = {
|
|||||||
@:structInit class TMeshData {
|
@:structInit class TMeshData {
|
||||||
#end
|
#end
|
||||||
public var name: String;
|
public var name: String;
|
||||||
public var sorting_index: Int;
|
|
||||||
public var vertex_arrays: Array<TVertexArray>;
|
public var vertex_arrays: Array<TVertexArray>;
|
||||||
public var index_arrays: Array<TIndexArray>;
|
public var index_arrays: Array<TIndexArray>;
|
||||||
@:optional public var dynamic_usage: Null<Bool>;
|
@:optional public var dynamic_usage: Null<Bool>;
|
||||||
@ -223,7 +222,6 @@ typedef TShaderData = {
|
|||||||
@:structInit class TShaderData {
|
@:structInit class TShaderData {
|
||||||
#end
|
#end
|
||||||
public var name: String;
|
public var name: String;
|
||||||
public var next_pass: String;
|
|
||||||
public var contexts: Array<TShaderContext>;
|
public var contexts: Array<TShaderContext>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,9 +392,6 @@ typedef TParticleData = {
|
|||||||
#end
|
#end
|
||||||
public var name: String;
|
public var name: String;
|
||||||
public var type: Int; // 0 - Emitter, Hair
|
public var type: Int; // 0 - Emitter, Hair
|
||||||
public var auto_start: Bool;
|
|
||||||
public var dynamic_emitter: Bool;
|
|
||||||
public var is_unique: Bool;
|
|
||||||
public var loop: Bool;
|
public var loop: Bool;
|
||||||
public var count: Int;
|
public var count: Int;
|
||||||
public var frame_start: FastFloat;
|
public var frame_start: FastFloat;
|
||||||
@ -444,7 +439,6 @@ typedef TObj = {
|
|||||||
@:optional public var traits: Array<TTrait>;
|
@:optional public var traits: Array<TTrait>;
|
||||||
@:optional public var properties: Array<TProperty>;
|
@:optional public var properties: Array<TProperty>;
|
||||||
@:optional public var vertex_groups: Array<TVertex_groups>;
|
@:optional public var vertex_groups: Array<TVertex_groups>;
|
||||||
@:optional public var camera_list: Array<String>;
|
|
||||||
@:optional public var constraints: Array<TConstraint>;
|
@:optional public var constraints: Array<TConstraint>;
|
||||||
@:optional public var dimensions: Float32Array; // Geometry objects
|
@:optional public var dimensions: Float32Array; // Geometry objects
|
||||||
@:optional public var object_actions: Array<String>;
|
@:optional public var object_actions: Array<String>;
|
||||||
|
|||||||
@ -22,7 +22,6 @@ using StringTools;
|
|||||||
class ShaderData {
|
class ShaderData {
|
||||||
|
|
||||||
public var name: String;
|
public var name: String;
|
||||||
public var nextPass: String;
|
|
||||||
public var raw: TShaderData;
|
public var raw: TShaderData;
|
||||||
public var contexts: Array<ShaderContext> = [];
|
public var contexts: Array<ShaderContext> = [];
|
||||||
|
|
||||||
@ -34,7 +33,6 @@ class ShaderData {
|
|||||||
public function new(raw: TShaderData, done: ShaderData->Void, overrideContext: TShaderOverride = null) {
|
public function new(raw: TShaderData, done: ShaderData->Void, overrideContext: TShaderOverride = null) {
|
||||||
this.raw = raw;
|
this.raw = raw;
|
||||||
this.name = raw.name;
|
this.name = raw.name;
|
||||||
this.nextPass = raw.next_pass;
|
|
||||||
|
|
||||||
for (c in raw.contexts) contexts.push(null);
|
for (c in raw.contexts) contexts.push(null);
|
||||||
var contextsLoaded = 0;
|
var contextsLoaded = 0;
|
||||||
|
|||||||
@ -114,7 +114,6 @@ class TerrainStream {
|
|||||||
|
|
||||||
var rawmeshData: TMeshData = {
|
var rawmeshData: TMeshData = {
|
||||||
name: "Terrain",
|
name: "Terrain",
|
||||||
sorting_index: 0,
|
|
||||||
vertex_arrays: [pos, nor, tex],
|
vertex_arrays: [pos, nor, tex],
|
||||||
index_arrays: [ind],
|
index_arrays: [ind],
|
||||||
scale_pos: scalePos,
|
scale_pos: scalePos,
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* format - Haxe File Formats
|
|
||||||
*
|
|
||||||
* BMP File Format
|
|
||||||
* Copyright (C) 2007-2009 Trevor McCauley, Baluta Cristian (hx port) & Robert Sköld (format conversion)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009, The Haxe Project Contributors
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* - Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
* DAMAGE.
|
|
||||||
*/
|
|
||||||
package iron.format.bmp;
|
|
||||||
|
|
||||||
typedef Data = {
|
|
||||||
var header : iron.format.bmp.Header;
|
|
||||||
var pixels : haxe.io.Bytes;
|
|
||||||
#if (haxe_ver < 4)
|
|
||||||
var colorTable : Null<haxe.io.Bytes>;
|
|
||||||
#else
|
|
||||||
var ?colorTable : haxe.io.Bytes;
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef Header = {
|
|
||||||
var width : Int; // real width (in pixels)
|
|
||||||
var height : Int; // real height (in pixels)
|
|
||||||
var paddedStride : Int; // number of bytes in a stride (including padding)
|
|
||||||
var topToBottom : Bool; // whether the bitmap is stored top to bottom
|
|
||||||
var bpp : Int; // bits per pixel
|
|
||||||
var dataLength : Int; // equal to `paddedStride` * `height`
|
|
||||||
var compression : Int; // which compression is being used, 0 for no compression
|
|
||||||
}
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* format - Haxe File Formats
|
|
||||||
*
|
|
||||||
* BMP File Format
|
|
||||||
* Copyright (C) 2007-2009 Robert Sköld
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009, The Haxe Project Contributors
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* - Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
* DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package iron.format.bmp;
|
|
||||||
|
|
||||||
import iron.format.bmp.Data;
|
|
||||||
|
|
||||||
|
|
||||||
class Reader {
|
|
||||||
|
|
||||||
var input : haxe.io.Input;
|
|
||||||
|
|
||||||
public function new( i ) {
|
|
||||||
input = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Only supports uncompressed 24bpp bitmaps (the most common format).
|
|
||||||
*
|
|
||||||
* The returned bytes in `Data.pixels` will be in BGR order, and with padding (if present).
|
|
||||||
*
|
|
||||||
* @see https://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx
|
|
||||||
* @see https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header
|
|
||||||
*/
|
|
||||||
public function read() : format.bmp.Data {
|
|
||||||
// Read Header
|
|
||||||
for (b in ["B".code, "M".code]) {
|
|
||||||
if (input.readByte() != b) throw "Invalid header";
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileSize = input.readInt32();
|
|
||||||
input.readInt32(); // Reserved
|
|
||||||
var offset = input.readInt32();
|
|
||||||
|
|
||||||
// Read InfoHeader
|
|
||||||
var infoHeaderSize = input.readInt32(); // InfoHeader size
|
|
||||||
if (infoHeaderSize != 40) {
|
|
||||||
throw 'Info headers with size $infoHeaderSize not supported.';
|
|
||||||
}
|
|
||||||
var width = input.readInt32(); // Image width (actual, not padded)
|
|
||||||
var height = input.readInt32(); // Image height
|
|
||||||
var numPlanes = input.readInt16(); // Number of planes
|
|
||||||
var bits = input.readInt16(); // Bits per pixel
|
|
||||||
var compression = input.readInt32(); // Compression type
|
|
||||||
var dataLength = input.readInt32(); // Image data size (includes padding!)
|
|
||||||
input.readInt32(); // Horizontal resolution
|
|
||||||
input.readInt32(); // Vertical resolution
|
|
||||||
var colorsUsed = input.readInt32(); // Colors used (0 when uncompressed)
|
|
||||||
input.readInt32(); // Important colors (0 when uncompressed)
|
|
||||||
|
|
||||||
// If there's no compression, the dataLength may be 0
|
|
||||||
if ( compression == 0 && dataLength == 0 ) dataLength = fileSize - offset;
|
|
||||||
|
|
||||||
var bytesRead = 54; // total read above
|
|
||||||
|
|
||||||
var colorTable : haxe.io.Bytes = null;
|
|
||||||
if ( bits <= 8 ) {
|
|
||||||
if ( colorsUsed == 0 ) {
|
|
||||||
colorsUsed = Tools.getNumColorsForBitDepth(bits);
|
|
||||||
}
|
|
||||||
var colorTableLength = 4 * colorsUsed;
|
|
||||||
colorTable = haxe.io.Bytes.alloc( colorTableLength );
|
|
||||||
input.readFullBytes( colorTable, 0, colorTableLength );
|
|
||||||
bytesRead += colorTableLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.read( offset - bytesRead );
|
|
||||||
|
|
||||||
var p = haxe.io.Bytes.alloc( dataLength );
|
|
||||||
|
|
||||||
// Read Raster Data
|
|
||||||
var paddedStride = Tools.computePaddedStride(width, bits);
|
|
||||||
var topToBottom = false;
|
|
||||||
if ( height < 0 ) { // if bitmap is stored top to bottom
|
|
||||||
topToBottom = true;
|
|
||||||
height = -height;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.readFullBytes(p, 0, dataLength);
|
|
||||||
|
|
||||||
return {
|
|
||||||
header: {
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
paddedStride: paddedStride,
|
|
||||||
topToBottom: topToBottom,
|
|
||||||
bpp: bits,
|
|
||||||
dataLength: dataLength,
|
|
||||||
compression: compression
|
|
||||||
},
|
|
||||||
pixels: p,
|
|
||||||
colorTable: colorTable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,256 +0,0 @@
|
|||||||
/*
|
|
||||||
* format - Haxe File Formats
|
|
||||||
*
|
|
||||||
* BMP File Format
|
|
||||||
* Copyright (C) 2007-2009 Trevor McCauley, Baluta Cristian (hx port) & Robert Sköld (format conversion)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009, The Haxe Project Contributors
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* - Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
* DAMAGE.
|
|
||||||
*/
|
|
||||||
package iron.format.bmp;
|
|
||||||
|
|
||||||
|
|
||||||
class Tools {
|
|
||||||
|
|
||||||
// a r g b
|
|
||||||
static var ARGB_MAP(default, never):Array<Int> = [0, 1, 2, 3];
|
|
||||||
static var BGRA_MAP(default, never):Array<Int> = [3, 2, 1, 0];
|
|
||||||
|
|
||||||
static var COLOR_SIZE(default, never):Int = 4;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Extract BMP pixel data (24bpp in BGR format) and expands it to BGRA, removing any padding in the process.
|
|
||||||
**/
|
|
||||||
inline static public function extractBGRA( bmp : iron.format.bmp.Data ) : haxe.io.Bytes {
|
|
||||||
return _extract32(bmp, BGRA_MAP, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Extract BMP pixel data (24bpp in BGR format) and converts it to ARGB.
|
|
||||||
**/
|
|
||||||
inline static public function extractARGB( bmp : iron.format.bmp.Data ) : haxe.io.Bytes {
|
|
||||||
return _extract32(bmp, ARGB_MAP, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Creates BMP data from bytes in BGRA format for each pixel.
|
|
||||||
**/
|
|
||||||
inline static public function buildFromBGRA( width : Int, height : Int, srcBytes : haxe.io.Bytes, topToBottom : Bool = false ) : Data {
|
|
||||||
return _buildFrom32(width, height, srcBytes, BGRA_MAP, topToBottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Creates BMP data from bytes in ARGB format for each pixel.
|
|
||||||
**/
|
|
||||||
inline static public function buildFromARGB( width : Int, height : Int, srcBytes : haxe.io.Bytes, topToBottom : Bool = false ) : Data {
|
|
||||||
return _buildFrom32(width, height, srcBytes, ARGB_MAP, topToBottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static public function computePaddedStride(width:Int, bpp:Int):Int {
|
|
||||||
return ((((width * bpp) + 31) & ~31) >> 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets number of colors for indexed palettes
|
|
||||||
*/
|
|
||||||
inline static public function getNumColorsForBitDepth(bpp:Int):Int {
|
|
||||||
return switch (bpp) {
|
|
||||||
case 1: 2;
|
|
||||||
case 4: 16;
|
|
||||||
case 8: 256;
|
|
||||||
case 16: 65536;
|
|
||||||
default: throw 'Unsupported bpp $bpp';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// `channelMap` contains indices to map into ARGB (f.e. the mapping for ARGB is [0,1,2,3], while for BGRA is [3,2,1,0])
|
|
||||||
static function _extract32( bmp : iron.format.bmp.Data, channelMap : Array<Int>, alpha : Int = 0xFF) : haxe.io.Bytes {
|
|
||||||
var srcBytes = bmp.pixels;
|
|
||||||
var dstLen = bmp.header.width * bmp.header.height * 4;
|
|
||||||
var dstBytes = haxe.io.Bytes.alloc( dstLen );
|
|
||||||
var srcPaddedStride = bmp.header.paddedStride;
|
|
||||||
|
|
||||||
var yDir = -1;
|
|
||||||
var dstPos = 0;
|
|
||||||
var srcPos = srcPaddedStride * (bmp.header.height - 1);
|
|
||||||
|
|
||||||
if ( bmp.header.topToBottom ) {
|
|
||||||
yDir = 1;
|
|
||||||
srcPos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bmp.header.bpp < 8 || bmp.header.bpp == 16 ) {
|
|
||||||
throw 'bpp ${bmp.header.bpp} not supported';
|
|
||||||
}
|
|
||||||
|
|
||||||
var colorTable:haxe.io.Bytes = null;
|
|
||||||
if ( bmp.header.bpp <= 8 ) {
|
|
||||||
var colorTableLength = getNumColorsForBitDepth(bmp.header.bpp);
|
|
||||||
colorTable = haxe.io.Bytes.alloc(colorTableLength * COLOR_SIZE);
|
|
||||||
var definedColorTableLength = Std.int( bmp.colorTable.length / COLOR_SIZE );
|
|
||||||
for( i in 0...definedColorTableLength ) {
|
|
||||||
var b = bmp.colorTable.get( i * COLOR_SIZE);
|
|
||||||
var g = bmp.colorTable.get( i * COLOR_SIZE + 1);
|
|
||||||
var r = bmp.colorTable.get( i * COLOR_SIZE + 2);
|
|
||||||
|
|
||||||
colorTable.set(i * COLOR_SIZE + channelMap[0], alpha);
|
|
||||||
colorTable.set(i * COLOR_SIZE + channelMap[1], r);
|
|
||||||
colorTable.set(i * COLOR_SIZE + channelMap[2], g);
|
|
||||||
colorTable.set(i * COLOR_SIZE + channelMap[3], b);
|
|
||||||
}
|
|
||||||
// We want to have the table the full length in case indices outside the range are present
|
|
||||||
colorTable.fill(definedColorTableLength, colorTableLength - definedColorTableLength, 0);
|
|
||||||
for( i in definedColorTableLength...colorTableLength ) {
|
|
||||||
colorTable.set(i * COLOR_SIZE + channelMap[0], alpha);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch bmp.header.compression {
|
|
||||||
case 0:
|
|
||||||
while( dstPos < dstLen ) {
|
|
||||||
for( i in 0...bmp.header.width ) {
|
|
||||||
if (bmp.header.bpp == 8) {
|
|
||||||
|
|
||||||
var currentSrcPos = srcPos + i;
|
|
||||||
var index = srcBytes.get(currentSrcPos);
|
|
||||||
dstBytes.blit( dstPos, colorTable, index * COLOR_SIZE, COLOR_SIZE );
|
|
||||||
|
|
||||||
} else if (bmp.header.bpp == 24) {
|
|
||||||
|
|
||||||
var currentSrcPos = srcPos + i * 3;
|
|
||||||
var b = srcBytes.get(currentSrcPos);
|
|
||||||
var g = srcBytes.get(currentSrcPos + 1);
|
|
||||||
var r = srcBytes.get(currentSrcPos + 2);
|
|
||||||
|
|
||||||
dstBytes.set(dstPos + channelMap[0], alpha);
|
|
||||||
dstBytes.set(dstPos + channelMap[1], r);
|
|
||||||
dstBytes.set(dstPos + channelMap[2], g);
|
|
||||||
dstBytes.set(dstPos + channelMap[3], b);
|
|
||||||
|
|
||||||
} else if (bmp.header.bpp == 32) {
|
|
||||||
|
|
||||||
var currentSrcPos = srcPos + i * 4;
|
|
||||||
var b = srcBytes.get(currentSrcPos);
|
|
||||||
var g = srcBytes.get(currentSrcPos + 1);
|
|
||||||
var r = srcBytes.get(currentSrcPos + 2);
|
|
||||||
|
|
||||||
dstBytes.set(dstPos + channelMap[0], alpha);
|
|
||||||
dstBytes.set(dstPos + channelMap[1], r);
|
|
||||||
dstBytes.set(dstPos + channelMap[2], g);
|
|
||||||
dstBytes.set(dstPos + channelMap[3], b);
|
|
||||||
|
|
||||||
}
|
|
||||||
dstPos += 4;
|
|
||||||
}
|
|
||||||
srcPos += yDir * srcPaddedStride;
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
srcPos = 0;
|
|
||||||
var x = 0;
|
|
||||||
var y = bmp.header.topToBottom ? 0 : bmp.header.height - 1;
|
|
||||||
while( srcPos < bmp.header.dataLength ) {
|
|
||||||
var count = srcBytes.get(srcPos++);
|
|
||||||
var index = srcBytes.get(srcPos++);
|
|
||||||
if ( count == 0 ) {
|
|
||||||
if ( index == 0 ) {
|
|
||||||
x = 0;
|
|
||||||
y += yDir;
|
|
||||||
} else if ( index == 1 ) {
|
|
||||||
break;
|
|
||||||
} else if ( index == 2 ) {
|
|
||||||
x += srcBytes.get(srcPos++);
|
|
||||||
y += srcBytes.get(srcPos++);
|
|
||||||
} else {
|
|
||||||
count = index;
|
|
||||||
for( i in 0...count ) {
|
|
||||||
index = srcBytes.get(srcPos++);
|
|
||||||
dstBytes.blit( COLOR_SIZE * ((x+i) + y * bmp.header.width), colorTable, index * COLOR_SIZE, COLOR_SIZE );
|
|
||||||
}
|
|
||||||
if (srcPos % 2 != 0) srcPos++;
|
|
||||||
x += count;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for( i in 0...count ) {
|
|
||||||
dstBytes.blit( COLOR_SIZE * ((x+i) + y * bmp.header.width), colorTable, index * COLOR_SIZE, COLOR_SIZE );
|
|
||||||
}
|
|
||||||
x += count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw 'compression ${bmp.header.compression} not supported';
|
|
||||||
}
|
|
||||||
|
|
||||||
return dstBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// `channelMap` contains indices to map into ARGB (f.e. the mapping for ARGB is [0,1,2,3], while for BGRA is [3,2,1,0])
|
|
||||||
static function _buildFrom32( width : Int, height : Int, srcBytes : haxe.io.Bytes, channelMap : Array<Int>, topToBottom : Bool = false ) : Data {
|
|
||||||
var bpp = 24;
|
|
||||||
var paddedStride = computePaddedStride(width, bpp);
|
|
||||||
var bytesBGR = haxe.io.Bytes.alloc(paddedStride * height);
|
|
||||||
var topToBottom = topToBottom;
|
|
||||||
var dataLength = bytesBGR.length;
|
|
||||||
|
|
||||||
var dstStride = width * 3;
|
|
||||||
var srcLen = width * height * 4;
|
|
||||||
var yDir = -1;
|
|
||||||
var dstPos = dataLength - paddedStride;
|
|
||||||
var srcPos = 0;
|
|
||||||
|
|
||||||
if ( topToBottom ) {
|
|
||||||
yDir = 1;
|
|
||||||
dstPos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( srcPos < srcLen ) {
|
|
||||||
var i = dstPos;
|
|
||||||
while( i < dstPos + dstStride ) {
|
|
||||||
var r = srcBytes.get(srcPos + channelMap[1]);
|
|
||||||
var g = srcBytes.get(srcPos + channelMap[2]);
|
|
||||||
var b = srcBytes.get(srcPos + channelMap[3]);
|
|
||||||
|
|
||||||
bytesBGR.set(i++, b);
|
|
||||||
bytesBGR.set(i++, g);
|
|
||||||
bytesBGR.set(i++, r);
|
|
||||||
|
|
||||||
srcPos += 4;
|
|
||||||
}
|
|
||||||
dstPos += yDir * paddedStride;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
header: {
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
paddedStride: paddedStride,
|
|
||||||
topToBottom: topToBottom,
|
|
||||||
bpp: bpp,
|
|
||||||
dataLength: dataLength,
|
|
||||||
compression: 0
|
|
||||||
},
|
|
||||||
pixels: bytesBGR,
|
|
||||||
colorTable: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* format - Haxe File Formats
|
|
||||||
*
|
|
||||||
* BMP File Format
|
|
||||||
* Copyright (C) 2007-2009 Robert Sköld
|
|
||||||
*
|
|
||||||
* Copyright (c) 2009, The Haxe Project Contributors
|
|
||||||
* All rights reserved.
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* - Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* - Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
||||||
* DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package iron.format.bmp;
|
|
||||||
|
|
||||||
import iron.format.bmp.Data;
|
|
||||||
|
|
||||||
|
|
||||||
class Writer {
|
|
||||||
|
|
||||||
static var DATA_OFFSET : Int = 0x36;
|
|
||||||
|
|
||||||
var output : haxe.io.Output;
|
|
||||||
|
|
||||||
public function new(o) {
|
|
||||||
output = o;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specs: http://s223767089.online.de/en/file-format-bmp
|
|
||||||
*/
|
|
||||||
public function write( bmp : Data ) {
|
|
||||||
// Write Header (14 bytes)
|
|
||||||
output.writeString( "BM" ); // Signature
|
|
||||||
output.writeInt32(bmp.pixels.length + DATA_OFFSET ); // FileSize
|
|
||||||
output.writeInt32( 0 ); // Reserved
|
|
||||||
output.writeInt32( DATA_OFFSET ); // Offset
|
|
||||||
|
|
||||||
// Write InfoHeader (40 bytes)
|
|
||||||
output.writeInt32( 40 ); // InfoHeader size
|
|
||||||
output.writeInt32( bmp.header.width ); // Image width
|
|
||||||
var height = bmp.header.height;
|
|
||||||
if (bmp.header.topToBottom) height = -height;
|
|
||||||
output.writeInt32( height ); // Image height
|
|
||||||
output.writeInt16( 1 ); // Number of planes
|
|
||||||
output.writeInt16( 24 ); // Bits per pixel (24bit RGB)
|
|
||||||
output.writeInt32( 0 ); // Compression type (no compression)
|
|
||||||
output.writeInt32( bmp.header.dataLength ); // Image data size (0 when uncompressed)
|
|
||||||
output.writeInt32( 0x2e30 ); // Horizontal resolution
|
|
||||||
output.writeInt32( 0x2e30 ); // Vertical resolution
|
|
||||||
output.writeInt32( 0 ); // Colors used (0 when uncompressed)
|
|
||||||
output.writeInt32( 0 ); // Important colors (0 when uncompressed)
|
|
||||||
|
|
||||||
// Write Raster Data
|
|
||||||
output.write(bmp.pixels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -141,7 +141,6 @@ class Animation {
|
|||||||
sampler.cacheSet = false;
|
sampler.cacheSet = false;
|
||||||
sampler.trackEnd = false;
|
sampler.trackEnd = false;
|
||||||
|
|
||||||
if (anim == null || anim.tracks == null || anim.tracks.length == 0) return;
|
|
||||||
var track = anim.tracks[0];
|
var track = anim.tracks[0];
|
||||||
|
|
||||||
if (frameIndex == -1) {
|
if (frameIndex == -1) {
|
||||||
@ -160,17 +159,9 @@ class Animation {
|
|||||||
if(markerEvents.get(sampler) != null){
|
if(markerEvents.get(sampler) != null){
|
||||||
for (i in 0...anim.marker_frames.length) {
|
for (i in 0...anim.marker_frames.length) {
|
||||||
if (frameIndex == anim.marker_frames[i]) {
|
if (frameIndex == anim.marker_frames[i]) {
|
||||||
var markerAct = markerEvents.get(sampler);
|
var marketAct = markerEvents.get(sampler);
|
||||||
var ar = markerAct.get(anim.marker_names[i]);
|
var ar = marketAct.get(anim.marker_names[i]);
|
||||||
if (ar != null) for (f in ar) f();
|
if (ar != null) for (f in ar) f();
|
||||||
} else {
|
|
||||||
for (j in 0...(frameIndex - lastFrameIndex)) {
|
|
||||||
if (lastFrameIndex + j + 1 == anim.marker_frames[i]) {
|
|
||||||
var markerAct = markerEvents.get(sampler);
|
|
||||||
var ar = markerAct.get(anim.marker_names[i]);
|
|
||||||
if (ar != null) for (f in ar) f();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastFrameIndex = frameIndex;
|
lastFrameIndex = frameIndex;
|
||||||
@ -443,12 +434,7 @@ class ActionSampler {
|
|||||||
*/
|
*/
|
||||||
public inline function setObjectAction(actionData: TObj) {
|
public inline function setObjectAction(actionData: TObj) {
|
||||||
this.actionData = [actionData];
|
this.actionData = [actionData];
|
||||||
if (actionData != null && actionData.anim != null && actionData.anim.tracks != null && actionData.anim.tracks.length > 0) {
|
|
||||||
this.totalFrames = actionData.anim.tracks[0].frames.length;
|
this.totalFrames = actionData.anim.tracks[0].frames.length;
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.totalFrames = 0;
|
|
||||||
}
|
|
||||||
actionDataInit = true;
|
actionDataInit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -108,13 +108,11 @@ class BoneAnimation extends Animation {
|
|||||||
object.transform.rot.set(0, 0, 0, 1);
|
object.transform.rot.set(0, 0, 0, 1);
|
||||||
object.transform.buildMatrix();
|
object.transform.buildMatrix();
|
||||||
|
|
||||||
if (mo.parent != null && mo.parent.raw != null && mo.parent.raw.bone_actions != null) {
|
|
||||||
var refs = mo.parent.raw.bone_actions;
|
var refs = mo.parent.raw.bone_actions;
|
||||||
if (refs.length > 0) {
|
if (refs != null && refs.length > 0) {
|
||||||
Data.getSceneRaw(refs[0], function(action: TSceneFormat) { play(action.name); });
|
Data.getSceneRaw(refs[0], function(action: TSceneFormat) { play(action.name); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (armatureObject.raw.relative_bone_constraints) relativeBoneConstraints = true;
|
if (armatureObject.raw.relative_bone_constraints) relativeBoneConstraints = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -185,10 +183,8 @@ class BoneAnimation extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setAction(action: String) {
|
function setAction(action: String) {
|
||||||
if (armature == null) return;
|
|
||||||
armature.initMats();
|
armature.initMats();
|
||||||
var a = armature.getAction(action);
|
var a = armature.getAction(action);
|
||||||
if (a == null) return;
|
|
||||||
skeletonBones = a.bones;
|
skeletonBones = a.bones;
|
||||||
skeletonMats = a.mats;
|
skeletonMats = a.mats;
|
||||||
if(! rootMotionCacheInit) skeletonMats.push(Mat4.identity());
|
if(! rootMotionCacheInit) skeletonMats.push(Mat4.identity());
|
||||||
@ -197,11 +193,8 @@ class BoneAnimation extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getAction(action: String): Array<TObj> {
|
function getAction(action: String): Array<TObj> {
|
||||||
if (armature == null) return null;
|
|
||||||
armature.initMats();
|
armature.initMats();
|
||||||
var a = armature.getAction(action);
|
return armature.getAction(action).bones;
|
||||||
if (a == null) return null;
|
|
||||||
return a.bones;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function multParent(i: Int, fasts: Array<Mat4>, bones: Array<TObj>, mats: Array<Mat4>) {
|
function multParent(i: Int, fasts: Array<Mat4>, bones: Array<TObj>, mats: Array<Mat4>) {
|
||||||
@ -232,9 +225,9 @@ class BoneAnimation extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.2, speed = 1.0, loop = true) {
|
override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.2, speed = 1.0, loop = true) {
|
||||||
|
super.play(action, onComplete, blendTime, speed, loop);
|
||||||
if (action != "") {
|
if (action != "") {
|
||||||
setAction(action);
|
setAction(action);
|
||||||
super.play(action, onComplete, blendTime, speed, loop);
|
|
||||||
var tempAnimParam = new ActionSampler(action);
|
var tempAnimParam = new ActionSampler(action);
|
||||||
registerAction("tempAction", tempAnimParam);
|
registerAction("tempAction", tempAnimParam);
|
||||||
updateAnimation = function(mats){
|
updateAnimation = function(mats){
|
||||||
@ -246,10 +239,6 @@ class BoneAnimation extends Animation {
|
|||||||
override public function update(delta: FastFloat) {
|
override public function update(delta: FastFloat) {
|
||||||
this.delta = delta;
|
this.delta = delta;
|
||||||
if (!isSkinned && skeletonBones == null) setAction(armature.actions[0].name);
|
if (!isSkinned && skeletonBones == null) setAction(armature.actions[0].name);
|
||||||
|
|
||||||
// TODO: double check skip culling for skinned meshes if they need animation updates for bounds
|
|
||||||
// if (object != null && !object.visible) return;
|
|
||||||
|
|
||||||
if (object != null && (!object.visible || object.culled)) return;
|
if (object != null && (!object.visible || object.culled)) return;
|
||||||
if (skeletonBones == null || skeletonBones.length == 0) return;
|
if (skeletonBones == null || skeletonBones.length == 0) return;
|
||||||
|
|
||||||
@ -259,6 +248,7 @@ class BoneAnimation extends Animation {
|
|||||||
|
|
||||||
super.update(delta);
|
super.update(delta);
|
||||||
if(updateAnimation != null) {
|
if(updateAnimation != null) {
|
||||||
|
|
||||||
updateAnimation(skeletonMats);
|
updateAnimation(skeletonMats);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,7 +401,6 @@ class BoneAnimation extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var bones = sampler.getBoneAction();
|
var bones = sampler.getBoneAction();
|
||||||
if (bones == null) return;
|
|
||||||
for(b in bones){
|
for(b in bones){
|
||||||
if (b.anim != null) {
|
if (b.anim != null) {
|
||||||
updateTrack(b.anim, sampler);
|
updateTrack(b.anim, sampler);
|
||||||
@ -421,14 +410,13 @@ class BoneAnimation extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function sampleAction(sampler: ActionSampler, actionMats: Array<Mat4>) {
|
public function sampleAction(sampler: ActionSampler, actionMats: Array<Mat4>) {
|
||||||
|
|
||||||
if(! sampler.actionDataInit) {
|
if(! sampler.actionDataInit) {
|
||||||
var bones = getAction(sampler.action);
|
var bones = getAction(sampler.action);
|
||||||
sampler.setBoneAction(bones);
|
sampler.setBoneAction(bones);
|
||||||
}
|
}
|
||||||
|
|
||||||
var bones = sampler.getBoneAction();
|
var bones = sampler.getBoneAction();
|
||||||
if (bones == null) return;
|
|
||||||
|
|
||||||
actionMats[skeletonBones.length].setIdentity();
|
actionMats[skeletonBones.length].setIdentity();
|
||||||
var rootMotionEnabled = sampler.rootMotionPos || sampler.rootMotionRot;
|
var rootMotionEnabled = sampler.rootMotionPos || sampler.rootMotionRot;
|
||||||
for (i in 0...bones.length) {
|
for (i in 0...bones.length) {
|
||||||
@ -439,6 +427,7 @@ class BoneAnimation extends Animation {
|
|||||||
updateAnimSampled(bones[i].anim, actionMats[i], sampler);
|
updateAnimSampled(bones[i].anim, actionMats[i], sampler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateAnimSampled(anim: TAnimation, mm: Mat4, sampler: ActionSampler) {
|
function updateAnimSampled(anim: TAnimation, mm: Mat4, sampler: ActionSampler) {
|
||||||
@ -599,9 +588,6 @@ class BoneAnimation extends Animation {
|
|||||||
|
|
||||||
public override function getTotalFrames(sampler: ActionSampler): Int {
|
public override function getTotalFrames(sampler: ActionSampler): Int {
|
||||||
var bones = getAction(sampler.action);
|
var bones = getAction(sampler.action);
|
||||||
if (bones == null){
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
var track = bones[0].anim.tracks[0];
|
var track = bones[0].anim.tracks[0];
|
||||||
return Std.int(track.frames[track.frames.length - 1] - track.frames[0]);
|
return Std.int(track.frames[track.frames.length - 1] - track.frames[0]);
|
||||||
}
|
}
|
||||||
@ -1062,9 +1048,9 @@ class BoneAnimation extends Animation {
|
|||||||
var rootLen = root.bone_length * rootMat.getScale().x;
|
var rootLen = root.bone_length * rootMat.getScale().x;
|
||||||
|
|
||||||
// Get distance form root to goal
|
// Get distance form root to goal
|
||||||
var goalLen: FastFloat = Math.abs(Vec4.distance(rootMat.getLoc(), goal));
|
var goalLen = Math.abs(Vec4.distance(rootMat.getLoc(), goal));
|
||||||
|
|
||||||
var totalLength: FastFloat = effectorLen + rootLen;
|
var totalLength = effectorLen + rootLen;
|
||||||
|
|
||||||
// Get tip location of effector bone
|
// Get tip location of effector bone
|
||||||
var effectorTipPos = new Vec4().setFrom(effectorMat.look()).normalize();
|
var effectorTipPos = new Vec4().setFrom(effectorMat.look()).normalize();
|
||||||
|
|||||||
@ -31,22 +31,11 @@ class CameraObject extends Object {
|
|||||||
static var vcenter = new Vec4();
|
static var vcenter = new Vec4();
|
||||||
static var vup = new Vec4();
|
static var vup = new Vec4();
|
||||||
|
|
||||||
#if lnx_vr
|
|
||||||
var helpMat = Mat4.identity();
|
|
||||||
public var leftV = Mat4.identity();
|
|
||||||
public var rightV = Mat4.identity();
|
|
||||||
#end
|
|
||||||
|
|
||||||
public function new(data: CameraData) {
|
public function new(data: CameraData) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
|
||||||
// dont just auto initialize VR button - headset trait controls VR
|
|
||||||
// #if lnx_vr
|
|
||||||
// iron.system.VR.initButton();
|
|
||||||
// #end
|
|
||||||
|
|
||||||
buildProjection();
|
buildProjection();
|
||||||
|
|
||||||
V = Mat4.identity();
|
V = Mat4.identity();
|
||||||
@ -86,14 +75,7 @@ class CameraObject extends Object {
|
|||||||
projectionJitter();
|
projectionJitter();
|
||||||
#end
|
#end
|
||||||
|
|
||||||
// matrices are set by VR system so avoid rebuilding transforms unless its in preview/not presenting
|
|
||||||
#if (kha_webgl && lnx_vr)
|
|
||||||
if (@:privateAccess !RenderPath.isVRPresenting()) {
|
|
||||||
buildMatrix();
|
buildMatrix();
|
||||||
}
|
|
||||||
#else
|
|
||||||
buildMatrix();
|
|
||||||
#end
|
|
||||||
|
|
||||||
RenderPath.active.renderFrame(g);
|
RenderPath.active.renderFrame(g);
|
||||||
|
|
||||||
@ -135,26 +117,6 @@ class CameraObject extends Object {
|
|||||||
V.getInverse(transform.world);
|
V.getInverse(transform.world);
|
||||||
VP.multmats(P, V);
|
VP.multmats(P, V);
|
||||||
|
|
||||||
|
|
||||||
#if lnx_vr
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr != null && vr.IsPresenting()) {
|
|
||||||
leftV.setFrom(V);
|
|
||||||
helpMat.self = vr.GetViewMatrix(0);
|
|
||||||
leftV.multmat(helpMat);
|
|
||||||
|
|
||||||
rightV.setFrom(V);
|
|
||||||
helpMat.self = vr.GetViewMatrix(1);
|
|
||||||
rightV.multmat(helpMat);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
leftV.setFrom(V);
|
|
||||||
}
|
|
||||||
VP.multmats(P, leftV);
|
|
||||||
#else
|
|
||||||
VP.multmats(P, V);
|
|
||||||
#end
|
|
||||||
|
|
||||||
if (data.raw.frustum_culling) {
|
if (data.raw.frustum_culling) {
|
||||||
buildViewFrustum(VP, frustumPlanes);
|
buildViewFrustum(VP, frustumPlanes);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,9 +59,6 @@ class LightObject extends Object {
|
|||||||
public static var clustersData: kha.Image = null;
|
public static var clustersData: kha.Image = null;
|
||||||
static var lpos = new Vec4();
|
static var lpos = new Vec4();
|
||||||
public static var LWVPMatrixArray: Float32Array = null;
|
public static var LWVPMatrixArray: Float32Array = null;
|
||||||
#if lnx_vr
|
|
||||||
static var originalLightPositions: Float32Array = null;
|
|
||||||
#end
|
|
||||||
#end // lnx_clusters
|
#end // lnx_clusters
|
||||||
|
|
||||||
public var V: Mat4 = Mat4.identity();
|
public var V: Mat4 = Mat4.identity();
|
||||||
@ -158,12 +155,7 @@ class LightObject extends Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function setCascade(camera: CameraObject, cascade: Int) {
|
public function setCascade(camera: CameraObject, cascade: Int) {
|
||||||
|
|
||||||
#if lnx_vr
|
|
||||||
m.setFrom(camera.leftV);
|
|
||||||
#else
|
|
||||||
m.setFrom(camera.V);
|
m.setFrom(camera.V);
|
||||||
#end
|
|
||||||
|
|
||||||
#if lnx_csm
|
#if lnx_csm
|
||||||
if (camSlicedP == null) {
|
if (camSlicedP == null) {
|
||||||
@ -522,7 +514,7 @@ class LightObject extends Object {
|
|||||||
updateLightsArray(); // TODO: only update on light change
|
updateLightsArray(); // TODO: only update on light change
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function updateLightsArray() {
|
static function updateLightsArray() {
|
||||||
if (lightsArray == null) { // vec4x3 - 1: pos, a, color, b, 2: dir, c
|
if (lightsArray == null) { // vec4x3 - 1: pos, a, color, b, 2: dir, c
|
||||||
lightsArray = new Float32Array(maxLights * 4 * 3);
|
lightsArray = new Float32Array(maxLights * 4 * 3);
|
||||||
#if lnx_spot
|
#if lnx_spot
|
||||||
@ -581,49 +573,6 @@ class LightObject extends Object {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VR deferred stereo we save original light positions before adjusting for per-eye rendering
|
|
||||||
#if lnx_vr
|
|
||||||
public static function saveOriginalLightPositions() {
|
|
||||||
if (lightsArray == null) return;
|
|
||||||
|
|
||||||
if (originalLightPositions == null) {
|
|
||||||
originalLightPositions = new Float32Array(lightsArray.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0...lightsArray.length) {
|
|
||||||
originalLightPositions[i] = lightsArray[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// negative for left eye, positive for right eye
|
|
||||||
public static function adjustLightPositionsForVREye(offsetX: Float, rightVec: Vec4) {
|
|
||||||
if (lightsArray == null) return;
|
|
||||||
|
|
||||||
var lights = Scene.active.lights;
|
|
||||||
var n = lights.length > maxLights ? maxLights : lights.length;
|
|
||||||
var i = 0;
|
|
||||||
|
|
||||||
for (l in lights) {
|
|
||||||
if (discardLightCulled(l)) continue;
|
|
||||||
if (i >= n) break;
|
|
||||||
|
|
||||||
lightsArray[i * 12 ] = originalLightPositions[i * 12 ] + rightVec.x * offsetX;
|
|
||||||
lightsArray[i * 12 + 1] = originalLightPositions[i * 12 + 1] + rightVec.y * offsetX;
|
|
||||||
lightsArray[i * 12 + 2] = originalLightPositions[i * 12 + 2] + rightVec.z * offsetX;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function restoreOriginalLightPositions() {
|
|
||||||
if (lightsArray == null || originalLightPositions == null) return;
|
|
||||||
|
|
||||||
for (i in 0...lightsArray.length) {
|
|
||||||
lightsArray[i] = originalLightPositions[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
public static function updateLWVPMatrixArray(object: Object, type: String) {
|
public static function updateLWVPMatrixArray(object: Object, type: String) {
|
||||||
if (LWVPMatrixArray == null) {
|
if (LWVPMatrixArray == null) {
|
||||||
LWVPMatrixArray = new Float32Array(maxLightsCluster * 16);
|
LWVPMatrixArray = new Float32Array(maxLightsCluster * 16);
|
||||||
@ -675,8 +624,8 @@ class LightObject extends Object {
|
|||||||
LWVPMatrixArray[i * 16 + 13] = m._31;
|
LWVPMatrixArray[i * 16 + 13] = m._31;
|
||||||
LWVPMatrixArray[i * 16 + 14] = m._32;
|
LWVPMatrixArray[i * 16 + 14] = m._32;
|
||||||
LWVPMatrixArray[i * 16 + 15] = m._33;
|
LWVPMatrixArray[i * 16 + 15] = m._33;
|
||||||
i++; // only increment in light type
|
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
return LWVPMatrixArray;
|
return LWVPMatrixArray;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,10 +21,8 @@ class MeshObject extends Object {
|
|||||||
public var particleChildren: Array<MeshObject> = null;
|
public var particleChildren: Array<MeshObject> = null;
|
||||||
public var particleOwner: MeshObject = null; // Particle object
|
public var particleOwner: MeshObject = null; // Particle object
|
||||||
public var particleIndex = -1;
|
public var particleIndex = -1;
|
||||||
public var render_emitter = true;
|
|
||||||
#end
|
#end
|
||||||
public var cameraDistance: Float;
|
public var cameraDistance: Float;
|
||||||
public var cameraList: Array<String> = null;
|
|
||||||
public var screenSize = 0.0;
|
public var screenSize = 0.0;
|
||||||
public var frustumCulling = true;
|
public var frustumCulling = true;
|
||||||
public var activeTilesheet: Tilesheet = null;
|
public var activeTilesheet: Tilesheet = null;
|
||||||
@ -236,8 +234,6 @@ class MeshObject extends Object {
|
|||||||
if (cullMesh(context, Scene.active.camera, RenderPath.active.light)) return;
|
if (cullMesh(context, Scene.active.camera, RenderPath.active.light)) return;
|
||||||
var meshContext = raw != null ? context == "mesh" : false;
|
var meshContext = raw != null ? context == "mesh" : false;
|
||||||
|
|
||||||
if (cameraList != null && cameraList.indexOf(Scene.active.camera.name) < 0) return;
|
|
||||||
|
|
||||||
#if lnx_particles
|
#if lnx_particles
|
||||||
if (raw != null && raw.is_particle && particleOwner == null) return; // Instancing not yet set-up by particle system owner
|
if (raw != null && raw.is_particle && particleOwner == null) return; // Instancing not yet set-up by particle system owner
|
||||||
if (particleSystems != null && meshContext) {
|
if (particleSystems != null && meshContext) {
|
||||||
@ -248,7 +244,6 @@ class MeshObject extends Object {
|
|||||||
Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
|
Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
|
||||||
if (o != null) {
|
if (o != null) {
|
||||||
var c: MeshObject = cast o;
|
var c: MeshObject = cast o;
|
||||||
c.cameraList = this.cameraList;
|
|
||||||
particleChildren.push(c);
|
particleChildren.push(c);
|
||||||
c.particleOwner = this;
|
c.particleOwner = this;
|
||||||
c.particleIndex = particleChildren.length - 1;
|
c.particleIndex = particleChildren.length - 1;
|
||||||
@ -260,11 +255,11 @@ class MeshObject extends Object {
|
|||||||
particleSystems[i].update(particleChildren[i], this);
|
particleSystems[i].update(particleChildren[i], this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (particleSystems != null && particleSystems.length > 0 && !render_emitter) return;
|
if (particleSystems != null && particleSystems.length > 0 && !raw.render_emitter) return;
|
||||||
if (particleSystems == null && cullMaterial(context)) return;
|
|
||||||
#else
|
|
||||||
if (cullMaterial(context)) return;
|
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
if (cullMaterial(context)) return;
|
||||||
|
|
||||||
// Get lod
|
// Get lod
|
||||||
var mats = materials;
|
var mats = materials;
|
||||||
var lod = this;
|
var lod = this;
|
||||||
@ -302,10 +297,6 @@ class MeshObject extends Object {
|
|||||||
|
|
||||||
// Render mesh
|
// Render mesh
|
||||||
var ldata = lod.data;
|
var ldata = lod.data;
|
||||||
|
|
||||||
// Next pass rendering first (inverse order)
|
|
||||||
renderNextPass(g, context, bindParams, lod);
|
|
||||||
|
|
||||||
for (i in 0...ldata.geom.indexBuffers.length) {
|
for (i in 0...ldata.geom.indexBuffers.length) {
|
||||||
|
|
||||||
var mi = ldata.geom.materialIndices[i];
|
var mi = ldata.geom.materialIndices[i];
|
||||||
@ -409,85 +400,4 @@ class MeshObject extends Object {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function renderNextPass(g: Graphics, context: String, bindParams: Array<String>, lod: MeshObject) {
|
|
||||||
var ldata = lod.data;
|
|
||||||
for (i in 0...ldata.geom.indexBuffers.length) {
|
|
||||||
var mi = ldata.geom.materialIndices[i];
|
|
||||||
if (mi >= materials.length) continue;
|
|
||||||
|
|
||||||
var currentMaterial: MaterialData = materials[mi];
|
|
||||||
if (currentMaterial == null || currentMaterial.shader == null) continue;
|
|
||||||
|
|
||||||
var nextPassName: String = currentMaterial.shader.nextPass;
|
|
||||||
if (nextPassName == null || nextPassName == "") continue;
|
|
||||||
|
|
||||||
var nextMaterial: MaterialData = null;
|
|
||||||
for (mat in materials) {
|
|
||||||
// First try exact match
|
|
||||||
if (mat.name == nextPassName) {
|
|
||||||
nextMaterial = mat;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// If no exact match, try to match base name for linked materials
|
|
||||||
if (mat.name.indexOf("_") > 0 && mat.name.substr(mat.name.length - 6) == ".blend") {
|
|
||||||
var baseName = mat.name.substring(0, mat.name.indexOf("_"));
|
|
||||||
if (baseName == nextPassName) {
|
|
||||||
nextMaterial = mat;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextMaterial == null) continue;
|
|
||||||
|
|
||||||
var nextMaterialContext: MaterialContext = null;
|
|
||||||
var nextShaderContext: ShaderContext = null;
|
|
||||||
|
|
||||||
for (j in 0...nextMaterial.raw.contexts.length) {
|
|
||||||
if (nextMaterial.raw.contexts[j].name.substr(0, context.length) == context) {
|
|
||||||
nextMaterialContext = nextMaterial.contexts[j];
|
|
||||||
nextShaderContext = nextMaterial.shader.getContext(context);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextShaderContext == null) continue;
|
|
||||||
if (skipContext(context, nextMaterial)) continue;
|
|
||||||
|
|
||||||
var elems = nextShaderContext.raw.vertex_elements;
|
|
||||||
|
|
||||||
// Uniforms
|
|
||||||
if (nextShaderContext.pipeState != lastPipeline) {
|
|
||||||
g.setPipeline(nextShaderContext.pipeState);
|
|
||||||
lastPipeline = nextShaderContext.pipeState;
|
|
||||||
}
|
|
||||||
Uniforms.setContextConstants(g, nextShaderContext, bindParams);
|
|
||||||
Uniforms.setObjectConstants(g, nextShaderContext, this);
|
|
||||||
Uniforms.setMaterialConstants(g, nextShaderContext, nextMaterialContext);
|
|
||||||
|
|
||||||
// VB / IB
|
|
||||||
#if lnx_deinterleaved
|
|
||||||
g.setVertexBuffers(ldata.geom.get(elems));
|
|
||||||
#else
|
|
||||||
if (ldata.geom.instancedVB != null) {
|
|
||||||
g.setVertexBuffers([ldata.geom.get(elems), ldata.geom.instancedVB]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g.setVertexBuffer(ldata.geom.get(elems));
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
g.setIndexBuffer(ldata.geom.indexBuffers[i]);
|
|
||||||
|
|
||||||
// Draw next pass for this specific geometry section
|
|
||||||
if (ldata.geom.instanced) {
|
|
||||||
g.drawIndexedVerticesInstanced(ldata.geom.instanceCount, ldata.geom.start, ldata.geom.count);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
g.drawIndexedVertices(ldata.geom.start, ldata.geom.count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -57,10 +57,6 @@ class MorphTarget {
|
|||||||
morphWeights.set(i, value);
|
morphWeights.set(i, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline function setMorphValueDirect(index: Int, value: Float) {
|
|
||||||
morphWeights.set(index, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#end
|
#end
|
||||||
|
|||||||
@ -172,10 +172,6 @@ class Object {
|
|||||||
for (f in t._init) App.removeInit(f);
|
for (f in t._init) App.removeInit(f);
|
||||||
t._init = null;
|
t._init = null;
|
||||||
}
|
}
|
||||||
if (t._fixedUpdate != null) {
|
|
||||||
for (f in t._fixedUpdate) App.removeFixedUpdate(f);
|
|
||||||
t._fixedUpdate = null;
|
|
||||||
}
|
|
||||||
if (t._update != null) {
|
if (t._update != null) {
|
||||||
for (f in t._update) App.removeUpdate(f);
|
for (f in t._update) App.removeUpdate(f);
|
||||||
t._update = null;
|
t._update = null;
|
||||||
@ -210,12 +206,8 @@ class Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if lnx_skin
|
#if lnx_skin
|
||||||
public function getBoneAnimation(armatureUid: Int): BoneAnimation {
|
public function getBoneAnimation(armatureUid): BoneAnimation {
|
||||||
for (a in Scene.active.animations) {
|
for (a in Scene.active.animations) if (a.armature != null && a.armature.uid == armatureUid) return cast a;
|
||||||
if (a.armature != null && a.armature.uid == armatureUid) {
|
|
||||||
return cast a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -24,9 +24,6 @@ class ObjectAnimation extends Animation {
|
|||||||
|
|
||||||
public var transformMap: Map<String, FastFloat>;
|
public var transformMap: Map<String, FastFloat>;
|
||||||
|
|
||||||
var defaultSampler: ActionSampler = null;
|
|
||||||
static inline var DEFAULT_SAMPLER_ID = "__object_default_action__";
|
|
||||||
|
|
||||||
public static var trackNames: Array<String> = [ "xloc", "yloc", "zloc",
|
public static var trackNames: Array<String> = [ "xloc", "yloc", "zloc",
|
||||||
"xrot", "yrot", "zrot",
|
"xrot", "yrot", "zrot",
|
||||||
"qwrot", "qxrot", "qyrot", "qzrot",
|
"qwrot", "qxrot", "qyrot", "qzrot",
|
||||||
@ -42,6 +39,7 @@ class ObjectAnimation extends Animation {
|
|||||||
isSkinned = false;
|
isSkinned = false;
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAction(action: String): TObj {
|
function getAction(action: String): TObj {
|
||||||
for (a in oactions) if (a != null && a.objects[0].name == action) return a.objects[0];
|
for (a in oactions) if (a != null && a.objects[0].name == action) return a.objects[0];
|
||||||
return null;
|
return null;
|
||||||
@ -49,29 +47,10 @@ class ObjectAnimation extends Animation {
|
|||||||
|
|
||||||
override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.0, speed = 1.0, loop = true) {
|
override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.0, speed = 1.0, loop = true) {
|
||||||
super.play(action, onComplete, blendTime, speed, loop);
|
super.play(action, onComplete, blendTime, speed, loop);
|
||||||
if (this.action == "" && oactions != null && oactions[0] != null){
|
if (this.action == "" && oactions[0] != null) this.action = oactions[0].objects[0].name;
|
||||||
this.action = oactions[0].objects[0].name;
|
|
||||||
}
|
|
||||||
oaction = getAction(this.action);
|
oaction = getAction(this.action);
|
||||||
if (oaction != null) {
|
if (oaction != null) {
|
||||||
isSampled = oaction.sampled != null && oaction.sampled;
|
isSampled = oaction.sampled != null && oaction.sampled;
|
||||||
if (defaultSampler != null) {
|
|
||||||
deRegisterAction(DEFAULT_SAMPLER_ID);
|
|
||||||
}
|
|
||||||
var callbacks = onComplete != null ? [onComplete] : null;
|
|
||||||
defaultSampler = new ActionSampler(this.action, speed, loop, false, callbacks);
|
|
||||||
registerAction(DEFAULT_SAMPLER_ID, defaultSampler);
|
|
||||||
if (paused) defaultSampler.paused = true;
|
|
||||||
updateAnimation = function(map: Map<String, FastFloat>) {
|
|
||||||
sampleAction(defaultSampler, map);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (defaultSampler != null) {
|
|
||||||
deRegisterAction(DEFAULT_SAMPLER_ID);
|
|
||||||
defaultSampler = null;
|
|
||||||
}
|
|
||||||
updateAnimation = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +65,6 @@ class ObjectAnimation extends Animation {
|
|||||||
transformMap = initTransformMap();
|
transformMap = initTransformMap();
|
||||||
|
|
||||||
super.update(delta);
|
super.update(delta);
|
||||||
if (defaultSampler != null) defaultSampler.paused = paused;
|
|
||||||
if (paused) return;
|
if (paused) return;
|
||||||
if(updateAnimation == null) return;
|
if(updateAnimation == null) return;
|
||||||
if (!isSkinned) updateObjectAnimation();
|
if (!isSkinned) updateObjectAnimation();
|
||||||
@ -97,9 +75,7 @@ class ObjectAnimation extends Animation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override function getTotalFrames(sampler: ActionSampler): Int {
|
public override function getTotalFrames(sampler: ActionSampler): Int {
|
||||||
var action = getAction(sampler.action);
|
var track = getAction(sampler.action).anim.tracks[0];
|
||||||
if (action == null || action.anim == null || action.anim.tracks == null || action.anim.tracks.length == 0) return 0;
|
|
||||||
var track = action.anim.tracks[0];
|
|
||||||
return Std.int(track.frames[track.frames.length - 1] - track.frames[0]);
|
return Std.int(track.frames[track.frames.length - 1] - track.frames[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,14 +2,11 @@ package iron.object;
|
|||||||
|
|
||||||
#if lnx_particles
|
#if lnx_particles
|
||||||
|
|
||||||
import kha.FastFloat;
|
|
||||||
import kha.graphics4.Usage;
|
import kha.graphics4.Usage;
|
||||||
import kha.arrays.Float32Array;
|
import kha.arrays.Float32Array;
|
||||||
import iron.data.Data;
|
import iron.data.Data;
|
||||||
import iron.data.ParticleData;
|
import iron.data.ParticleData;
|
||||||
import iron.data.SceneFormat;
|
import iron.data.SceneFormat;
|
||||||
import iron.data.Geometry;
|
|
||||||
import iron.data.MeshData;
|
|
||||||
import iron.system.Time;
|
import iron.system.Time;
|
||||||
import iron.math.Mat4;
|
import iron.math.Mat4;
|
||||||
import iron.math.Quat;
|
import iron.math.Quat;
|
||||||
@ -19,13 +16,10 @@ import iron.math.Vec4;
|
|||||||
class ParticleSystem {
|
class ParticleSystem {
|
||||||
public var data: ParticleData;
|
public var data: ParticleData;
|
||||||
public var speed = 1.0;
|
public var speed = 1.0;
|
||||||
public var dynamicEmitter: Bool = true;
|
|
||||||
var currentSpeed = 0.0;
|
|
||||||
var particles: Array<Particle>;
|
var particles: Array<Particle>;
|
||||||
var ready: Bool;
|
var ready: Bool;
|
||||||
var frameRate = 24;
|
var frameRate = 24;
|
||||||
var lifetime = 0.0;
|
var lifetime = 0.0;
|
||||||
var looptime = 0.0;
|
|
||||||
var animtime = 0.0;
|
var animtime = 0.0;
|
||||||
var time = 0.0;
|
var time = 0.0;
|
||||||
var spawnRate = 0.0;
|
var spawnRate = 0.0;
|
||||||
@ -53,30 +47,13 @@ class ParticleSystem {
|
|||||||
var ownerRot = new Quat();
|
var ownerRot = new Quat();
|
||||||
var ownerScl = new Vec4();
|
var ownerScl = new Vec4();
|
||||||
|
|
||||||
var random = 0.0;
|
|
||||||
|
|
||||||
var tmpV4 = new Vec4();
|
|
||||||
|
|
||||||
var instancedData: Float32Array = null;
|
|
||||||
var lastSpawnedCount: Int = 0;
|
|
||||||
var hasUniqueGeom: Bool = false;
|
|
||||||
|
|
||||||
public function new(sceneName: String, pref: TParticleReference) {
|
public function new(sceneName: String, pref: TParticleReference) {
|
||||||
seed = pref.seed;
|
seed = pref.seed;
|
||||||
currentSpeed = speed;
|
|
||||||
speed = 0;
|
|
||||||
particles = [];
|
particles = [];
|
||||||
ready = false;
|
ready = false;
|
||||||
|
|
||||||
Data.getParticle(sceneName, pref.particle, function(b: ParticleData) {
|
Data.getParticle(sceneName, pref.particle, function(b: ParticleData) {
|
||||||
data = b;
|
data = b;
|
||||||
r = data.raw;
|
r = data.raw;
|
||||||
var dyn: Null<Bool> = r.dynamic_emitter;
|
|
||||||
var dynValue: Bool = true;
|
|
||||||
if (dyn != null) {
|
|
||||||
dynValue = dyn;
|
|
||||||
}
|
|
||||||
dynamicEmitter = dynValue;
|
|
||||||
if (Scene.active.raw.gravity != null) {
|
if (Scene.active.raw.gravity != null) {
|
||||||
gx = Scene.active.raw.gravity[0] * r.weight_gravity;
|
gx = Scene.active.raw.gravity[0] * r.weight_gravity;
|
||||||
gy = Scene.active.raw.gravity[1] * r.weight_gravity;
|
gy = Scene.active.raw.gravity[1] * r.weight_gravity;
|
||||||
@ -87,73 +64,32 @@ class ParticleSystem {
|
|||||||
gy = 0;
|
gy = 0;
|
||||||
gz = -9.81 * r.weight_gravity;
|
gz = -9.81 * r.weight_gravity;
|
||||||
}
|
}
|
||||||
alignx = r.object_align_factor[0];
|
alignx = r.object_align_factor[0] / 2;
|
||||||
aligny = r.object_align_factor[1];
|
aligny = r.object_align_factor[1] / 2;
|
||||||
alignz = r.object_align_factor[2];
|
alignz = r.object_align_factor[2] / 2;
|
||||||
looptime = (r.frame_end - r.frame_start) / frameRate;
|
|
||||||
lifetime = r.lifetime / frameRate;
|
lifetime = r.lifetime / frameRate;
|
||||||
animtime = r.loop ? looptime : looptime + lifetime;
|
animtime = (r.frame_end - r.frame_start) / frameRate;
|
||||||
spawnRate = ((r.frame_end - r.frame_start) / r.count) / frameRate;
|
spawnRate = ((r.frame_end - r.frame_start) / r.count) / frameRate;
|
||||||
|
for (i in 0...r.count) particles.push(new Particle(i));
|
||||||
for (i in 0...r.count) {
|
|
||||||
particles.push(new Particle(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
ready = true;
|
ready = true;
|
||||||
if (r.auto_start){
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function start() {
|
|
||||||
if (r.is_unique) random = Math.random();
|
|
||||||
lifetime = r.lifetime / frameRate;
|
|
||||||
time = 0;
|
|
||||||
lap = 0;
|
|
||||||
lapTime = 0;
|
|
||||||
speed = currentSpeed;
|
|
||||||
lastSpawnedCount = 0;
|
|
||||||
instancedData = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pause() {
|
public function pause() {
|
||||||
speed = 0;
|
lifetime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resume() {
|
public function resume() {
|
||||||
lifetime = r.lifetime / frameRate;
|
lifetime = r.lifetime / frameRate;
|
||||||
speed = currentSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: interrupt smoothly
|
|
||||||
public function stop() {
|
|
||||||
end();
|
|
||||||
}
|
|
||||||
|
|
||||||
function end() {
|
|
||||||
lifetime = 0;
|
|
||||||
speed = 0;
|
|
||||||
lap = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(object: MeshObject, owner: MeshObject) {
|
public function update(object: MeshObject, owner: MeshObject) {
|
||||||
if (!ready || object == null || speed == 0.0) return;
|
if (!ready || object == null || speed == 0.0) return;
|
||||||
if (iron.App.pauseUpdates) return;
|
|
||||||
|
|
||||||
var prevLap = lap;
|
|
||||||
|
|
||||||
// Copy owner world transform but discard scale
|
// Copy owner world transform but discard scale
|
||||||
owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl);
|
owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl);
|
||||||
if (dynamicEmitter) {
|
|
||||||
object.transform.loc.x = 0; object.transform.loc.y = 0; object.transform.loc.z = 0;
|
|
||||||
object.transform.rot = new Quat();
|
|
||||||
} else {
|
|
||||||
object.transform.loc = ownerLoc;
|
object.transform.loc = ownerLoc;
|
||||||
object.transform.rot = ownerRot;
|
object.transform.rot = ownerRot;
|
||||||
}
|
|
||||||
|
|
||||||
// Set particle size per particle system
|
// Set particle size per particle system
|
||||||
object.transform.scale = new Vec4(r.particle_size, r.particle_size, r.particle_size, 1);
|
object.transform.scale = new Vec4(r.particle_size, r.particle_size, r.particle_size, 1);
|
||||||
@ -172,25 +108,16 @@ class ParticleSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Animate
|
// Animate
|
||||||
time += Time.renderDelta * speed; // realDelta to renderDelta
|
time += Time.realDelta * speed;
|
||||||
lap = Std.int(time / animtime);
|
lap = Std.int(time / animtime);
|
||||||
lapTime = time - lap * animtime;
|
lapTime = time - lap * animtime;
|
||||||
count = Std.int(lapTime / spawnRate);
|
count = Std.int(lapTime / spawnRate);
|
||||||
|
|
||||||
if (lap > prevLap && !r.loop) {
|
|
||||||
end();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lap > prevLap && r.loop) {
|
|
||||||
lastSpawnedCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateGpu(object, owner);
|
updateGpu(object, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getData(): Mat4 {
|
public function getData(): Mat4 {
|
||||||
var hair = r.type == 1;
|
var hair = r.type == 1;
|
||||||
// Store loop flag in the sign: positive -> loop, negative -> no loop
|
|
||||||
m._00 = r.loop ? animtime : -animtime;
|
m._00 = r.loop ? animtime : -animtime;
|
||||||
m._01 = hair ? 1 / particles.length : spawnRate;
|
m._01 = hair ? 1 / particles.length : spawnRate;
|
||||||
m._02 = hair ? 1 : lifetime;
|
m._02 = hair ? 1 : lifetime;
|
||||||
@ -199,9 +126,9 @@ class ParticleSystem {
|
|||||||
m._11 = hair ? 0 : aligny;
|
m._11 = hair ? 0 : aligny;
|
||||||
m._12 = hair ? 0 : alignz;
|
m._12 = hair ? 0 : alignz;
|
||||||
m._13 = hair ? 0 : r.factor_random;
|
m._13 = hair ? 0 : r.factor_random;
|
||||||
m._20 = hair ? 0 : gx;
|
m._20 = hair ? 0 : gx * r.mass;
|
||||||
m._21 = hair ? 0 : gy;
|
m._21 = hair ? 0 : gy * r.mass;
|
||||||
m._22 = hair ? 0 : gz;
|
m._22 = hair ? 0 : gz * r.mass;
|
||||||
m._23 = hair ? 0 : r.lifetime_random;
|
m._23 = hair ? 0 : r.lifetime_random;
|
||||||
m._30 = tilesx;
|
m._30 = tilesx;
|
||||||
m._31 = tilesy;
|
m._31 = tilesy;
|
||||||
@ -210,30 +137,9 @@ class ParticleSystem {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSizeRandom(): FastFloat {
|
|
||||||
return r.size_random;
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline function getRandom(): FastFloat {
|
|
||||||
return random;
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline function getSize(): FastFloat {
|
|
||||||
return r.particle_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateGpu(object: MeshObject, owner: MeshObject) {
|
function updateGpu(object: MeshObject, owner: MeshObject) {
|
||||||
if (dynamicEmitter) {
|
|
||||||
if (!hasUniqueGeom) ensureUniqueGeom(object);
|
|
||||||
var needSetup = instancedData == null || object.data.geom.instancedVB == null;
|
|
||||||
if (needSetup) setupGeomGpuDynamic(object, owner);
|
|
||||||
updateSpawnedInstances(object, owner);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!hasUniqueGeom) ensureUniqueGeom(object);
|
|
||||||
if (!object.data.geom.instanced) setupGeomGpu(object, owner);
|
if (!object.data.geom.instanced) setupGeomGpu(object, owner);
|
||||||
}
|
// GPU particles transform is attached to owner object
|
||||||
// GPU particles transform is attached to owner object in static mode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupGeomGpu(object: MeshObject, owner: MeshObject) {
|
function setupGeomGpu(object: MeshObject, owner: MeshObject) {
|
||||||
@ -294,123 +200,7 @@ class ParticleSystem {
|
|||||||
object.data.geom.setupInstanced(instancedData, 1, Usage.StaticUsage);
|
object.data.geom.setupInstanced(instancedData, 1, Usage.StaticUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate instanced VB once for this object
|
function fhash(n: Int): Float {
|
||||||
function setupGeomGpuDynamic(object: MeshObject, owner: MeshObject) {
|
|
||||||
if (instancedData == null) instancedData = new Float32Array(particles.length * 3);
|
|
||||||
lastSpawnedCount = 0;
|
|
||||||
// Create instanced VB once if missing (seed with our instancedData)
|
|
||||||
if (object.data.geom.instancedVB == null) {
|
|
||||||
object.data.geom.setupInstanced(instancedData, 1, Usage.DynamicUsage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensureUniqueGeom(object: MeshObject) {
|
|
||||||
if (hasUniqueGeom) return;
|
|
||||||
var newData: MeshData = null;
|
|
||||||
new MeshData(object.data.raw, function(dat: MeshData) {
|
|
||||||
dat.scalePos = object.data.scalePos;
|
|
||||||
dat.scaleTex = object.data.scaleTex;
|
|
||||||
dat.format = object.data.format;
|
|
||||||
newData = dat;
|
|
||||||
});
|
|
||||||
if (newData != null) object.setData(newData);
|
|
||||||
hasUniqueGeom = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSpawnedInstances(object: MeshObject, owner: MeshObject) {
|
|
||||||
if (instancedData == null) return;
|
|
||||||
var targetCount = count;
|
|
||||||
if (targetCount > particles.length) targetCount = particles.length;
|
|
||||||
if (targetCount <= lastSpawnedCount) return;
|
|
||||||
|
|
||||||
var normFactor = 1 / 32767;
|
|
||||||
var scalePosOwner = owner.data.scalePos;
|
|
||||||
var scalePosParticle = object.data.scalePos;
|
|
||||||
var particleSize = r.particle_size;
|
|
||||||
var base = 1.0 / (particleSize * scalePosParticle);
|
|
||||||
|
|
||||||
switch (r.emit_from) {
|
|
||||||
case 0: // Vert
|
|
||||||
var pa = owner.data.geom.positions;
|
|
||||||
var osx = owner.transform.scale.x;
|
|
||||||
var osy = owner.transform.scale.y;
|
|
||||||
var osz = owner.transform.scale.z;
|
|
||||||
var pCount = Std.int(pa.values.length / pa.size);
|
|
||||||
for (idx in lastSpawnedCount...targetCount) {
|
|
||||||
var j = Std.int(fhash(idx) * pCount);
|
|
||||||
var lx = pa.values[j * pa.size ] * normFactor * scalePosOwner * osx;
|
|
||||||
var ly = pa.values[j * pa.size + 1] * normFactor * scalePosOwner * osy;
|
|
||||||
var lz = pa.values[j * pa.size + 2] * normFactor * scalePosOwner * osz;
|
|
||||||
tmpV4.x = lx; tmpV4.y = ly; tmpV4.z = lz; tmpV4.w = 1;
|
|
||||||
tmpV4.applyQuat(ownerRot);
|
|
||||||
var o = idx * 3;
|
|
||||||
instancedData.set(o , (tmpV4.x + ownerLoc.x) * base);
|
|
||||||
instancedData.set(o + 1, (tmpV4.y + ownerLoc.y) * base);
|
|
||||||
instancedData.set(o + 2, (tmpV4.z + ownerLoc.z) * base);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1: // Face
|
|
||||||
var positions = owner.data.geom.positions.values;
|
|
||||||
var osx1 = owner.transform.scale.x;
|
|
||||||
var osy1 = owner.transform.scale.y;
|
|
||||||
var osz1 = owner.transform.scale.z;
|
|
||||||
for (idx in lastSpawnedCount...targetCount) {
|
|
||||||
var ia = owner.data.geom.indices[Std.random(owner.data.geom.indices.length)];
|
|
||||||
var faceIndex = Std.random(Std.int(ia.length / 3));
|
|
||||||
var i0 = ia[faceIndex * 3 + 0];
|
|
||||||
var i1 = ia[faceIndex * 3 + 1];
|
|
||||||
var i2 = ia[faceIndex * 3 + 2];
|
|
||||||
var v0x = positions[i0 * 4 ], v0y = positions[i0 * 4 + 1], v0z = positions[i0 * 4 + 2];
|
|
||||||
var v1x = positions[i1 * 4 ], v1y = positions[i1 * 4 + 1], v1z = positions[i1 * 4 + 2];
|
|
||||||
var v2x = positions[i2 * 4 ], v2y = positions[i2 * 4 + 1], v2z = positions[i2 * 4 + 2];
|
|
||||||
var rx = Math.random(); var ry = Math.random(); if (rx + ry > 1) { rx = 1 - rx; ry = 1 - ry; }
|
|
||||||
var pxs = v0x + rx * (v1x - v0x) + ry * (v2x - v0x);
|
|
||||||
var pys = v0y + rx * (v1y - v0y) + ry * (v2y - v0y);
|
|
||||||
var pzs = v0z + rx * (v1z - v0z) + ry * (v2z - v0z);
|
|
||||||
var px = pxs * normFactor * scalePosOwner * osx1;
|
|
||||||
var py = pys * normFactor * scalePosOwner * osy1;
|
|
||||||
var pz = pzs * normFactor * scalePosOwner * osz1;
|
|
||||||
tmpV4.x = px; tmpV4.y = py; tmpV4.z = pz; tmpV4.w = 1;
|
|
||||||
tmpV4.applyQuat(ownerRot);
|
|
||||||
var o1 = idx * 3;
|
|
||||||
instancedData.set(o1 , (tmpV4.x + ownerLoc.x) * base);
|
|
||||||
instancedData.set(o1 + 1, (tmpV4.y + ownerLoc.y) * base);
|
|
||||||
instancedData.set(o1 + 2, (tmpV4.z + ownerLoc.z) * base);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2: // Volume
|
|
||||||
var dim = object.transform.dim;
|
|
||||||
for (idx in lastSpawnedCount...targetCount) {
|
|
||||||
tmpV4.x = (Math.random() * 2.0 - 1.0) * (dim.x * 0.5);
|
|
||||||
tmpV4.y = (Math.random() * 2.0 - 1.0) * (dim.y * 0.5);
|
|
||||||
tmpV4.z = (Math.random() * 2.0 - 1.0) * (dim.z * 0.5);
|
|
||||||
tmpV4.w = 1;
|
|
||||||
tmpV4.applyQuat(ownerRot);
|
|
||||||
var o2 = idx * 3;
|
|
||||||
instancedData.set(o2 , (tmpV4.x + ownerLoc.x) * base);
|
|
||||||
instancedData.set(o2 + 1, (tmpV4.y + ownerLoc.y) * base);
|
|
||||||
instancedData.set(o2 + 2, (tmpV4.z + ownerLoc.z) * base);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload full active range [0..targetCount) to this object's instanced VB
|
|
||||||
var geom = object.data.geom;
|
|
||||||
if (geom.instancedVB == null) {
|
|
||||||
geom.setupInstanced(instancedData, 1, Usage.DynamicUsage);
|
|
||||||
}
|
|
||||||
var vb = geom.instancedVB.lock();
|
|
||||||
var totalFloats = targetCount * 3; // xyz per instance
|
|
||||||
var i = 0;
|
|
||||||
while (i < totalFloats) {
|
|
||||||
vb.setFloat32(i * 4, instancedData[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
geom.instancedVB.unlock();
|
|
||||||
geom.instanceCount = targetCount;
|
|
||||||
lastSpawnedCount = targetCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline function fhash(n: Int): Float {
|
|
||||||
var s = n + 1.0;
|
var s = n + 1.0;
|
||||||
s *= 9301.0 % s;
|
s *= 9301.0 % s;
|
||||||
s = (s * 9301.0 + 49297.0) % 233280.0;
|
s = (s * 9301.0 + 49297.0) % 233280.0;
|
||||||
@ -446,11 +236,9 @@ class ParticleSystem {
|
|||||||
|
|
||||||
class Particle {
|
class Particle {
|
||||||
public var i: Int;
|
public var i: Int;
|
||||||
|
|
||||||
public var x = 0.0;
|
public var x = 0.0;
|
||||||
public var y = 0.0;
|
public var y = 0.0;
|
||||||
public var z = 0.0;
|
public var z = 0.0;
|
||||||
|
|
||||||
public var cameraDistance: Float;
|
public var cameraDistance: Float;
|
||||||
|
|
||||||
public function new(i: Int) {
|
public function new(i: Int) {
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class Tilesheet {
|
|||||||
function update() {
|
function update() {
|
||||||
if (!ready || paused || action.start >= action.end) return;
|
if (!ready || paused || action.start >= action.end) return;
|
||||||
|
|
||||||
time += Time.renderDelta;
|
time += Time.realDelta;
|
||||||
|
|
||||||
var frameTime = 1 / raw.framerate;
|
var frameTime = 1 / raw.framerate;
|
||||||
var framesToAdvance = 0;
|
var framesToAdvance = 0;
|
||||||
|
|||||||
@ -7,20 +7,16 @@ import kha.graphics4.TextureFilter;
|
|||||||
import kha.graphics4.MipMapFilter;
|
import kha.graphics4.MipMapFilter;
|
||||||
import kha.arrays.Float32Array;
|
import kha.arrays.Float32Array;
|
||||||
import iron.math.Vec4;
|
import iron.math.Vec4;
|
||||||
import iron.math.Mat4;
|
|
||||||
import iron.math.Quat;
|
import iron.math.Quat;
|
||||||
import iron.math.Mat3;
|
import iron.math.Mat3;
|
||||||
|
import iron.math.Mat4;
|
||||||
|
import iron.data.WorldData;
|
||||||
import iron.data.MaterialData;
|
import iron.data.MaterialData;
|
||||||
import iron.data.ShaderData;
|
import iron.data.ShaderData;
|
||||||
import iron.data.WorldData;
|
import iron.data.SceneFormat;
|
||||||
import iron.data.SceneFormat.TShaderConstant;
|
|
||||||
import iron.data.SceneFormat.TBindConstant;
|
|
||||||
import iron.object.Transform;
|
|
||||||
import iron.object.LightObject;
|
|
||||||
import iron.Scene;
|
|
||||||
import iron.RenderPath;
|
|
||||||
import iron.system.Input;
|
import iron.system.Input;
|
||||||
import iron.system.Time;
|
import iron.system.Time;
|
||||||
|
import iron.RenderPath;
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
// Structure for setting shader uniforms
|
// Structure for setting shader uniforms
|
||||||
@ -42,7 +38,6 @@ class Uniforms {
|
|||||||
public static var helpMat = Mat4.identity();
|
public static var helpMat = Mat4.identity();
|
||||||
public static var helpMat2 = Mat4.identity();
|
public static var helpMat2 = Mat4.identity();
|
||||||
public static var helpMat3 = Mat3.identity();
|
public static var helpMat3 = Mat3.identity();
|
||||||
public static var helpMat4 = Mat4.identity();
|
|
||||||
public static var helpVec = new Vec4();
|
public static var helpVec = new Vec4();
|
||||||
public static var helpVec2 = new Vec4();
|
public static var helpVec2 = new Vec4();
|
||||||
public static var helpQuat = new Quat(); // Keep at identity
|
public static var helpQuat = new Quat(); // Keep at identity
|
||||||
@ -52,10 +47,6 @@ class Uniforms {
|
|||||||
public static var externalVec4Links: Array<Object->MaterialData->String->Vec4> = null;
|
public static var externalVec4Links: Array<Object->MaterialData->String->Vec4> = null;
|
||||||
public static var externalVec3Links: Array<Object->MaterialData->String->Vec4> = null;
|
public static var externalVec3Links: Array<Object->MaterialData->String->Vec4> = null;
|
||||||
public static var externalVec2Links: Array<Object->MaterialData->String->Vec4> = null;
|
public static var externalVec2Links: Array<Object->MaterialData->String->Vec4> = null;
|
||||||
|
|
||||||
public static var eyeLeftCallCount = 0;
|
|
||||||
public static var lastFrameChecked = -1;
|
|
||||||
|
|
||||||
public static var externalFloatLinks: Array<Object->MaterialData->String->Null<kha.FastFloat>> = null;
|
public static var externalFloatLinks: Array<Object->MaterialData->String->Null<kha.FastFloat>> = null;
|
||||||
public static var externalFloatsLinks: Array<Object->MaterialData->String->Float32Array> = null;
|
public static var externalFloatsLinks: Array<Object->MaterialData->String->Float32Array> = null;
|
||||||
public static var externalIntLinks: Array<Object->MaterialData->String->Null<Int>> = null;
|
public static var externalIntLinks: Array<Object->MaterialData->String->Null<Int>> = null;
|
||||||
@ -190,15 +181,11 @@ class Uniforms {
|
|||||||
// Multiple voxel volumes, always set params
|
// Multiple voxel volumes, always set params
|
||||||
g.setImageTexture(context.textureUnits[j], rt.image); // image2D/3D
|
g.setImageTexture(context.textureUnits[j], rt.image); // image2D/3D
|
||||||
if (rt.raw.name.startsWith("voxels_")) {
|
if (rt.raw.name.startsWith("voxels_")) {
|
||||||
g.setTextureParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.LinearMipFilter);
|
g.setTextureParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.NoMipFilter);
|
||||||
}
|
|
||||||
else if (rt.raw.name.startsWith("voxelsSDF"))
|
|
||||||
{
|
|
||||||
g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.PointFilter, TextureFilter.PointFilter, MipMapFilter.NoMipFilter);
|
|
||||||
}
|
}
|
||||||
else if (rt.raw.name.startsWith("voxels"))
|
else if (rt.raw.name.startsWith("voxels"))
|
||||||
{
|
{
|
||||||
g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.PointMipFilter);
|
g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.NoMipFilter);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -299,89 +286,6 @@ class Uniforms {
|
|||||||
helpMat.getInverse(helpMat);
|
helpMat.getInverse(helpMat);
|
||||||
m = helpMat;
|
m = helpMat;
|
||||||
}
|
}
|
||||||
#if lnx_vr
|
|
||||||
case "_inverseViewProjectionMatrixLeft": {
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr != null && vr.IsPresenting()) {
|
|
||||||
var leftView = vr.GetViewMatrix(0);
|
|
||||||
var leftProj = vr.GetProjectionMatrix(0);
|
|
||||||
helpMat._00 = leftView._00; helpMat._01 = leftView._01; helpMat._02 = leftView._02; helpMat._03 = leftView._03;
|
|
||||||
helpMat._10 = leftView._10; helpMat._11 = leftView._11; helpMat._12 = leftView._12; helpMat._13 = leftView._13;
|
|
||||||
helpMat._20 = leftView._20; helpMat._21 = leftView._21; helpMat._22 = leftView._22; helpMat._23 = leftView._23;
|
|
||||||
helpMat._30 = leftView._30; helpMat._31 = leftView._31; helpMat._32 = leftView._32; helpMat._33 = leftView._33;
|
|
||||||
helpMat2._00 = leftProj._00; helpMat2._01 = leftProj._01; helpMat2._02 = leftProj._02; helpMat2._03 = leftProj._03;
|
|
||||||
helpMat2._10 = leftProj._10; helpMat2._11 = leftProj._11; helpMat2._12 = leftProj._12; helpMat2._13 = leftProj._13;
|
|
||||||
helpMat2._20 = leftProj._20; helpMat2._21 = leftProj._21; helpMat2._22 = leftProj._22; helpMat2._23 = leftProj._23;
|
|
||||||
helpMat2._30 = leftProj._30; helpMat2._31 = leftProj._31; helpMat2._32 = leftProj._32; helpMat2._33 = leftProj._33;
|
|
||||||
helpMat.multmat(helpMat2);
|
|
||||||
helpMat.getInverse(helpMat);
|
|
||||||
} else if (iron.RenderPath.isVRSimulateMode()) {
|
|
||||||
var ipd_offset = 0.032 * 35.0; // Match eye offset
|
|
||||||
var rightVec = camera.rightWorld();
|
|
||||||
|
|
||||||
var eyeLeftX = camera.transform.worldx() - rightVec.x * ipd_offset;
|
|
||||||
var eyeLeftY = camera.transform.worldy() - rightVec.y * ipd_offset;
|
|
||||||
var eyeLeftZ = camera.transform.worldz() - rightVec.z * ipd_offset;
|
|
||||||
|
|
||||||
helpMat.setFrom(camera.transform.world);
|
|
||||||
helpMat._30 = eyeLeftX;
|
|
||||||
helpMat._31 = eyeLeftY;
|
|
||||||
helpMat._32 = eyeLeftZ;
|
|
||||||
helpMat.getInverse(helpMat); // Now it's a view matrix
|
|
||||||
|
|
||||||
helpMat.multmat(camera.P);
|
|
||||||
helpMat.getInverse(helpMat);
|
|
||||||
} else {
|
|
||||||
helpMat.setFrom(camera.V);
|
|
||||||
helpMat.multmat(camera.P);
|
|
||||||
helpMat.getInverse(helpMat);
|
|
||||||
}
|
|
||||||
m = helpMat;
|
|
||||||
}
|
|
||||||
case "_inverseViewProjectionMatrixRight": {
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr != null && vr.IsPresenting()) {
|
|
||||||
var rightView = vr.GetViewMatrix(1);
|
|
||||||
var rightProj = vr.GetProjectionMatrix(1);
|
|
||||||
// kha.math.FastMatrix4 to iron.math.Mat4
|
|
||||||
helpMat2._00 = rightView._00; helpMat2._01 = rightView._01; helpMat2._02 = rightView._02; helpMat2._03 = rightView._03;
|
|
||||||
helpMat2._10 = rightView._10; helpMat2._11 = rightView._11; helpMat2._12 = rightView._12; helpMat2._13 = rightView._13;
|
|
||||||
helpMat2._20 = rightView._20; helpMat2._21 = rightView._21; helpMat2._22 = rightView._22; helpMat2._23 = rightView._23;
|
|
||||||
helpMat2._30 = rightView._30; helpMat2._31 = rightView._31; helpMat2._32 = rightView._32; helpMat2._33 = rightView._33;
|
|
||||||
helpMat4._00 = rightProj._00; helpMat4._01 = rightProj._01; helpMat4._02 = rightProj._02; helpMat4._03 = rightProj._03;
|
|
||||||
helpMat4._10 = rightProj._10; helpMat4._11 = rightProj._11; helpMat4._12 = rightProj._12; helpMat4._13 = rightProj._13;
|
|
||||||
helpMat4._20 = rightProj._20; helpMat4._21 = rightProj._21; helpMat4._22 = rightProj._22; helpMat4._23 = rightProj._23;
|
|
||||||
helpMat4._30 = rightProj._30; helpMat4._31 = rightProj._31; helpMat4._32 = rightProj._32; helpMat4._33 = rightProj._33;
|
|
||||||
helpMat2.multmat(helpMat4);
|
|
||||||
helpMat2.getInverse(helpMat2);
|
|
||||||
m = helpMat2;
|
|
||||||
} else if (iron.RenderPath.isVRSimulateMode()) {
|
|
||||||
var ipd_offset = 0.032 * 35.0;
|
|
||||||
var rightVec = camera.rightWorld();
|
|
||||||
|
|
||||||
// calculate right eye position in world space
|
|
||||||
var eyeRightX = camera.transform.worldx() + rightVec.x * ipd_offset;
|
|
||||||
var eyeRightY = camera.transform.worldy() + rightVec.y * ipd_offset;
|
|
||||||
var eyeRightZ = camera.transform.worldz() + rightVec.z * ipd_offset;
|
|
||||||
|
|
||||||
helpMat2.setFrom(camera.transform.world);
|
|
||||||
helpMat2._30 = eyeRightX;
|
|
||||||
helpMat2._31 = eyeRightY;
|
|
||||||
helpMat2._32 = eyeRightZ;
|
|
||||||
helpMat2.getInverse(helpMat2);
|
|
||||||
|
|
||||||
helpMat2.multmat(camera.P);
|
|
||||||
helpMat2.getInverse(helpMat2);
|
|
||||||
m = helpMat2;
|
|
||||||
} else {
|
|
||||||
// fallback to center camera
|
|
||||||
helpMat2.setFrom(camera.V);
|
|
||||||
helpMat2.multmat(camera.P);
|
|
||||||
helpMat2.getInverse(helpMat2);
|
|
||||||
m = helpMat2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
case "_viewProjectionMatrix": {
|
case "_viewProjectionMatrix": {
|
||||||
#if lnx_centerworld
|
#if lnx_centerworld
|
||||||
m = vmat(camera.V);
|
m = vmat(camera.V);
|
||||||
@ -494,28 +398,6 @@ class Uniforms {
|
|||||||
v = helpVec;
|
v = helpVec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if lnx_vr
|
|
||||||
case "_pointPositionLeft": {
|
|
||||||
var point = RenderPath.active.point;
|
|
||||||
if (point != null) {
|
|
||||||
var lightWorldX = point.transform.worldx();
|
|
||||||
var lightWorldY = point.transform.worldy();
|
|
||||||
var lightWorldZ = point.transform.worldz();
|
|
||||||
helpVec.set(lightWorldX, lightWorldY, lightWorldZ);
|
|
||||||
v = helpVec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "_pointPositionRight": {
|
|
||||||
var point = RenderPath.active.point;
|
|
||||||
if (point != null) {
|
|
||||||
var lightWorldX = point.transform.worldx();
|
|
||||||
var lightWorldY = point.transform.worldy();
|
|
||||||
var lightWorldZ = point.transform.worldz();
|
|
||||||
helpVec.set(lightWorldX, lightWorldY, lightWorldZ);
|
|
||||||
v = helpVec;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
#if lnx_spot
|
#if lnx_spot
|
||||||
case "_spotDirection": {
|
case "_spotDirection": {
|
||||||
var point = RenderPath.active.point;
|
var point = RenderPath.active.point;
|
||||||
@ -602,84 +484,6 @@ class Uniforms {
|
|||||||
helpVec = camera.rightWorld().normalize();
|
helpVec = camera.rightWorld().normalize();
|
||||||
v = helpVec;
|
v = helpVec;
|
||||||
}
|
}
|
||||||
#if lnx_vr
|
|
||||||
case "_eyeLeft": {
|
|
||||||
var currentFrame = iron.RenderPath.active.frame;
|
|
||||||
if (currentFrame != lastFrameChecked) {
|
|
||||||
eyeLeftCallCount = 0;
|
|
||||||
lastFrameChecked = currentFrame;
|
|
||||||
}
|
|
||||||
eyeLeftCallCount++;
|
|
||||||
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr != null && vr.IsPresenting()) {
|
|
||||||
var leftViewMatrix = vr.GetViewMatrix(0);
|
|
||||||
var invLeft = leftViewMatrix.inverse();
|
|
||||||
helpVec.set(invLeft._30, invLeft._31, invLeft._32);
|
|
||||||
// trace("eyeLeft: " + helpVec.x + ", " + helpVec.y + ", " + helpVec.z);
|
|
||||||
} else if (iron.RenderPath.isVRSimulateMode()) {
|
|
||||||
var ipd_offset = 0.032 * 35.0;
|
|
||||||
var rightVec = camera.rightWorld();
|
|
||||||
var centerX = camera.transform.worldx();
|
|
||||||
var centerY = camera.transform.worldy();
|
|
||||||
var centerZ = camera.transform.worldz();
|
|
||||||
helpVec.set(
|
|
||||||
centerX - rightVec.x * ipd_offset,
|
|
||||||
centerY - rightVec.y * ipd_offset,
|
|
||||||
centerZ - rightVec.z * ipd_offset
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
helpVec.set(camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz());
|
|
||||||
}
|
|
||||||
v = helpVec;
|
|
||||||
}
|
|
||||||
case "_eyeRight": {
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr != null && vr.IsPresenting()) {
|
|
||||||
var rightViewMatrix = vr.GetViewMatrix(1);
|
|
||||||
var invRight = rightViewMatrix.inverse();
|
|
||||||
helpVec.set(invRight._30, invRight._31, invRight._32);
|
|
||||||
} else if (iron.RenderPath.isVRSimulateMode()) {
|
|
||||||
var ipd_offset = 0.032 * 35.0;
|
|
||||||
var rightVec = camera.rightWorld();
|
|
||||||
var centerX = camera.transform.worldx();
|
|
||||||
var centerY = camera.transform.worldy();
|
|
||||||
var centerZ = camera.transform.worldz();
|
|
||||||
helpVec.set(
|
|
||||||
centerX + rightVec.x * ipd_offset,
|
|
||||||
centerY + rightVec.y * ipd_offset,
|
|
||||||
centerZ + rightVec.z * ipd_offset
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
helpVec.set(camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz());
|
|
||||||
}
|
|
||||||
v = helpVec;
|
|
||||||
}
|
|
||||||
case "_eyeLookLeft": {
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr != null && vr.IsPresenting()) {
|
|
||||||
var leftViewMatrix = vr.GetViewMatrix(0);
|
|
||||||
var invLeft = leftViewMatrix.inverse();
|
|
||||||
helpVec.set(-invLeft._20, -invLeft._21, -invLeft._22);
|
|
||||||
helpVec.normalize();
|
|
||||||
} else {
|
|
||||||
helpVec = camera.lookWorld().normalize();
|
|
||||||
}
|
|
||||||
v = helpVec;
|
|
||||||
}
|
|
||||||
case "_eyeLookRight": {
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr != null && vr.IsPresenting()) {
|
|
||||||
var rightViewMatrix = vr.GetViewMatrix(1);
|
|
||||||
var invRight = rightViewMatrix.inverse();
|
|
||||||
helpVec.set(-invRight._20, -invRight._21, -invRight._22);
|
|
||||||
helpVec.normalize();
|
|
||||||
} else {
|
|
||||||
helpVec = camera.lookWorld().normalize();
|
|
||||||
}
|
|
||||||
v = helpVec;
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
case "_backgroundCol": {
|
case "_backgroundCol": {
|
||||||
if (camera.data.raw.clear_color != null) helpVec.set(camera.data.raw.clear_color[0], camera.data.raw.clear_color[1], camera.data.raw.clear_color[2]);
|
if (camera.data.raw.clear_color != null) helpVec.set(camera.data.raw.clear_color[0], camera.data.raw.clear_color[1], camera.data.raw.clear_color[2]);
|
||||||
v = helpVec;
|
v = helpVec;
|
||||||
@ -864,8 +668,7 @@ class Uniforms {
|
|||||||
f = iron.App.w() / iron.App.h();
|
f = iron.App.w() / iron.App.h();
|
||||||
}
|
}
|
||||||
case "_frameScale": {
|
case "_frameScale": {
|
||||||
var d = Time.delta;
|
f = RenderPath.active.frameTime / Time.delta;
|
||||||
f = d > 0.0001 ? Math.min(RenderPath.active.frameTime / d, 2.0) : 1.0;
|
|
||||||
}
|
}
|
||||||
case "_fieldOfView": {
|
case "_fieldOfView": {
|
||||||
f = camera.data.raw.fov;
|
f = camera.data.raw.fov;
|
||||||
@ -1306,26 +1109,6 @@ class Uniforms {
|
|||||||
case "_texUnpack": {
|
case "_texUnpack": {
|
||||||
f = texUnpack != null ? texUnpack : 1.0;
|
f = texUnpack != null ? texUnpack : 1.0;
|
||||||
}
|
}
|
||||||
#if lnx_particles
|
|
||||||
case "_particleSizeRandom": {
|
|
||||||
var mo = cast(object, MeshObject);
|
|
||||||
if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
|
|
||||||
f = mo.particleOwner.particleSystems[mo.particleIndex].getSizeRandom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "_particleRandom": {
|
|
||||||
var mo = cast(object, MeshObject);
|
|
||||||
if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
|
|
||||||
f = mo.particleOwner.particleSystems[mo.particleIndex].getRandom();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "_particleSize": {
|
|
||||||
var mo = cast(object, MeshObject);
|
|
||||||
if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
|
|
||||||
f = mo.particleOwner.particleSystems[mo.particleIndex].getSize();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f == null && externalFloatLinks != null) {
|
if (f == null && externalFloatLinks != null) {
|
||||||
@ -1400,7 +1183,6 @@ class Uniforms {
|
|||||||
if (materialContext.raw.bind_constants != null) {
|
if (materialContext.raw.bind_constants != null) {
|
||||||
for (i in 0...materialContext.raw.bind_constants.length) {
|
for (i in 0...materialContext.raw.bind_constants.length) {
|
||||||
var matc = materialContext.raw.bind_constants[i];
|
var matc = materialContext.raw.bind_constants[i];
|
||||||
if (matc == null) continue;
|
|
||||||
var pos = -1;
|
var pos = -1;
|
||||||
for (i in 0...context.raw.constants.length) {
|
for (i in 0...context.raw.constants.length) {
|
||||||
if (context.raw.constants[i].name == matc.name) {
|
if (context.raw.constants[i].name == matc.name) {
|
||||||
|
|||||||
@ -1,20 +1,6 @@
|
|||||||
package iron.system;
|
package iron.system;
|
||||||
|
|
||||||
class Time {
|
class Time {
|
||||||
public static var scale = 1.0;
|
|
||||||
|
|
||||||
// TODO: VR Frame Time Override - used to sync physics with VR headset refresh rate
|
|
||||||
#if lnx_vr
|
|
||||||
public static var vrFrameTime: Float = -1.0; // VR frame time in seconds (-1 = not in VR)
|
|
||||||
static var lastVRFrameTime: Float = 0.0;
|
|
||||||
static var vrFrameCount: Int = 0;
|
|
||||||
static var normalModeLogged: Bool = false;
|
|
||||||
#end
|
|
||||||
|
|
||||||
static var frequency: Null<Int> = null;
|
|
||||||
static function initFrequency() {
|
|
||||||
frequency = kha.Display.primary != null ? kha.Display.primary.frequency : 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var step(get, never): Float;
|
public static var step(get, never): Float;
|
||||||
static function get_step(): Float {
|
static function get_step(): Float {
|
||||||
@ -22,63 +8,30 @@ class Time {
|
|||||||
return 1 / frequency;
|
return 1 / frequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
static var _fixedStep: Null<Float> = 1/60;
|
public static var scale = 1.0;
|
||||||
public static var fixedStep(get, never): Float;
|
|
||||||
static function get_fixedStep(): Float {
|
|
||||||
return _fixedStep;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function initFixedStep(value: Float = 1 / 60) {
|
|
||||||
_fixedStep = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static var lastTime = 0.0;
|
|
||||||
static var _delta = 0.0;
|
|
||||||
public static var delta(get, never): Float;
|
public static var delta(get, never): Float;
|
||||||
static function get_delta(): Float {
|
static function get_delta(): Float {
|
||||||
return _delta;
|
if (frequency == null) initFrequency();
|
||||||
}
|
return (1 / frequency) * scale;
|
||||||
|
|
||||||
static var lastRenderTime = 0.0;
|
|
||||||
static var _renderDelta = 0.0;
|
|
||||||
public static var renderDelta(get, never): Float;
|
|
||||||
static function get_renderDelta(): Float {
|
|
||||||
return _renderDelta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static var last = 0.0;
|
||||||
|
public static var realDelta = 0.0;
|
||||||
public static inline function time(): Float {
|
public static inline function time(): Float {
|
||||||
return kha.Scheduler.time() * scale;
|
return kha.Scheduler.time();
|
||||||
|
}
|
||||||
|
public static inline function realTime(): Float {
|
||||||
|
return kha.Scheduler.realTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static inline function realTime(): Float {
|
static var frequency: Null<Int> = null;
|
||||||
return kha.Scheduler.realTime() * scale;
|
|
||||||
|
static function initFrequency() {
|
||||||
|
frequency = kha.Display.primary != null ? kha.Display.primary.frequency : 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function update() {
|
public static function update() {
|
||||||
#if lnx_vr
|
realDelta = realTime() - last;
|
||||||
// TODO: use VR frame time when in VR present mode to sync physics with headset refresh
|
last = realTime();
|
||||||
if (vrFrameTime >= 0.0) {
|
|
||||||
if (lastVRFrameTime > 0.0) {
|
|
||||||
_delta = vrFrameTime - lastVRFrameTime;
|
|
||||||
} else {
|
|
||||||
_delta = 1.0 / 90.0; // Default to 90Hz for first VR frame
|
|
||||||
}
|
|
||||||
lastVRFrameTime = vrFrameTime;
|
|
||||||
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (!normalModeLogged) {
|
|
||||||
normalModeLogged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
|
|
||||||
_delta = realTime() - lastTime;
|
|
||||||
lastTime = realTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function render() {
|
|
||||||
_renderDelta = realTime() - lastRenderTime;
|
|
||||||
lastRenderTime = realTime();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -94,34 +94,34 @@ class Tween {
|
|||||||
|
|
||||||
// Way too much Reflect trickery..
|
// Way too much Reflect trickery..
|
||||||
var ps = Reflect.fields(a.props);
|
var ps = Reflect.fields(a.props);
|
||||||
for (j in 0...ps.length) {
|
for (i in 0...ps.length) {
|
||||||
var p = ps[j];
|
var p = ps[i];
|
||||||
var k = a._time / a.duration;
|
var k = a._time / a.duration;
|
||||||
if (k > 1) k = 1;
|
if (k > 1) k = 1;
|
||||||
|
|
||||||
if (a._comps[j] == 1) {
|
if (a._comps[i] == 1) {
|
||||||
var fromVal: Float = a._x[j];
|
var fromVal: Float = a._x[i];
|
||||||
var toVal: Float = Reflect.getProperty(a.props, p);
|
var toVal: Float = Reflect.getProperty(a.props, p);
|
||||||
var val: Float = fromVal + (toVal - fromVal) * eases[a.ease](k);
|
var val: Float = fromVal + (toVal - fromVal) * eases[a.ease](k);
|
||||||
Reflect.setProperty(a.target, p, val);
|
Reflect.setProperty(a.target, p, val);
|
||||||
}
|
}
|
||||||
else { // _comps[j] == 4
|
else { // _comps[i] == 4
|
||||||
var obj = Reflect.getProperty(a.props, p);
|
var obj = Reflect.getProperty(a.props, p);
|
||||||
var toX: Float = Reflect.getProperty(obj, "x");
|
var toX: Float = Reflect.getProperty(obj, "x");
|
||||||
var toY: Float = Reflect.getProperty(obj, "y");
|
var toY: Float = Reflect.getProperty(obj, "y");
|
||||||
var toZ: Float = Reflect.getProperty(obj, "z");
|
var toZ: Float = Reflect.getProperty(obj, "z");
|
||||||
var toW: Float = Reflect.getProperty(obj, "w");
|
var toW: Float = Reflect.getProperty(obj, "w");
|
||||||
if (a._normalize[j]) {
|
if (a._normalize[i]) {
|
||||||
var qdot = (a._x[j] * toX) + (a._y[j] * toY) + (a._z[j] * toZ) + (a._w[j] * toW);
|
var qdot = (a._x[i] * toX) + (a._y[i] * toY) + (a._z[i] * toZ) + (a._w[i] * toW);
|
||||||
if (qdot < 0.0) {
|
if (qdot < 0.0) {
|
||||||
toX = -toX; toY = -toY; toZ = -toZ; toW = -toW;
|
toX = -toX; toY = -toY; toZ = -toZ; toW = -toW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var x: Float = a._x[j] + (toX - a._x[j]) * eases[a.ease](k);
|
var x: Float = a._x[i] + (toX - a._x[i]) * eases[a.ease](k);
|
||||||
var y: Float = a._y[j] + (toY - a._y[j]) * eases[a.ease](k);
|
var y: Float = a._y[i] + (toY - a._y[i]) * eases[a.ease](k);
|
||||||
var z: Float = a._z[j] + (toZ - a._z[j]) * eases[a.ease](k);
|
var z: Float = a._z[i] + (toZ - a._z[i]) * eases[a.ease](k);
|
||||||
var w: Float = a._w[j] + (toW - a._w[j]) * eases[a.ease](k);
|
var w: Float = a._w[i] + (toW - a._w[i]) * eases[a.ease](k);
|
||||||
if (a._normalize[j]) {
|
if (a._normalize[i]) {
|
||||||
var l = Math.sqrt(x * x + y * y + z * z + w * w);
|
var l = Math.sqrt(x * x + y * y + z * z + w * w);
|
||||||
if (l > 0.0) {
|
if (l > 0.0) {
|
||||||
l = 1.0 / l;
|
l = 1.0 / l;
|
||||||
|
|||||||
@ -1,52 +0,0 @@
|
|||||||
package iron.system;
|
|
||||||
|
|
||||||
import iron.math.Mat4;
|
|
||||||
|
|
||||||
#if lnx_vr
|
|
||||||
class VR {
|
|
||||||
|
|
||||||
static var undistortionMatrix: Mat4 = null;
|
|
||||||
|
|
||||||
public function new() {}
|
|
||||||
|
|
||||||
public static function getUndistortionMatrix(): Mat4 {
|
|
||||||
if (undistortionMatrix == null) {
|
|
||||||
undistortionMatrix = Mat4.identity();
|
|
||||||
}
|
|
||||||
|
|
||||||
return undistortionMatrix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getMaxRadiusSq(): Float {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function initButton() {
|
|
||||||
function vrDownListener(index: Int, x: Float, y: Float) {
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr == null || !vr.IsVrEnabled() || vr.IsPresenting()) return;
|
|
||||||
var w: Float = iron.App.w();
|
|
||||||
var h: Float = iron.App.h();
|
|
||||||
if (x < w - 150 || y < h - 150) return;
|
|
||||||
vr.onVRRequestPresent();
|
|
||||||
}
|
|
||||||
|
|
||||||
function vrRender2D(g: kha.graphics2.Graphics) {
|
|
||||||
var vr = kha.vr.VrInterface.instance;
|
|
||||||
if (vr == null || !vr.IsVrEnabled() || vr.IsPresenting()) return;
|
|
||||||
var w: Float = iron.App.w();
|
|
||||||
var h: Float = iron.App.h();
|
|
||||||
g.color = 0xffff0000;
|
|
||||||
g.fillRect(w - 150, h - 150, 140, 140);
|
|
||||||
}
|
|
||||||
|
|
||||||
kha.input.Mouse.get().notify(vrDownListener, null, null, null);
|
|
||||||
iron.App.notifyOnRender2D(vrRender2D);
|
|
||||||
|
|
||||||
var vr = kha.vr.VrInterface.instance; // Straight to VR (Oculus Carmel)
|
|
||||||
if (vr != null && vr.IsVrEnabled()) {
|
|
||||||
vr.onVRRequestPresent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
package iron.system;
|
|
||||||
|
|
||||||
#if lnx_vr
|
|
||||||
import iron.math.Vec4;
|
|
||||||
import iron.math.Quat;
|
|
||||||
|
|
||||||
class VRController {
|
|
||||||
|
|
||||||
public static var leftHandPosition: Vec4 = new Vec4();
|
|
||||||
public static var leftHandRotation: Quat = new Quat();
|
|
||||||
public static var rightHandPosition: Vec4 = new Vec4();
|
|
||||||
public static var rightHandRotation: Quat = new Quat();
|
|
||||||
|
|
||||||
public static var leftHandActive: Bool = false;
|
|
||||||
public static var rightHandActive: Bool = false;
|
|
||||||
|
|
||||||
public static var leftThumbstickX: Float = 0.0;
|
|
||||||
public static var leftThumbstickY: Float = 0.0;
|
|
||||||
public static var rightThumbstickX: Float = 0.0;
|
|
||||||
public static var rightThumbstickY: Float = 0.0;
|
|
||||||
|
|
||||||
public static var leftTrigger: Float = 0.0;
|
|
||||||
public static var rightTrigger: Float = 0.0;
|
|
||||||
public static var leftGrip: Float = 0.0;
|
|
||||||
public static var rightGrip: Float = 0.0;
|
|
||||||
|
|
||||||
public static var leftButtonX: Bool = false;
|
|
||||||
public static var leftButtonY: Bool = false;
|
|
||||||
public static var rightButtonA: Bool = false;
|
|
||||||
public static var rightButtonB: Bool = false;
|
|
||||||
|
|
||||||
public static var debugLog:Bool = false;
|
|
||||||
|
|
||||||
public static function enableDebug() {
|
|
||||||
debugLog = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function disableDebug() {
|
|
||||||
debugLog = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function updatePoses() {
|
|
||||||
var vr: kha.js.vr.VrInterface = cast kha.vr.VrInterface.instance;
|
|
||||||
if (vr == null || !vr.IsPresenting()) {
|
|
||||||
if (debugLog) trace("[VRController] Not presenting or VR null");
|
|
||||||
leftHandActive = false;
|
|
||||||
rightHandActive = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
untyped window._vrControllerFrame = (untyped window._vrControllerFrame || 0) + 1;
|
|
||||||
|
|
||||||
leftHandActive = false;
|
|
||||||
rightHandActive = false;
|
|
||||||
|
|
||||||
leftButtonX = false;
|
|
||||||
leftButtonY = false;
|
|
||||||
rightButtonA = false;
|
|
||||||
rightButtonB = false;
|
|
||||||
|
|
||||||
var refSpace = untyped vr.xrRefSpace;
|
|
||||||
if (vr.currentInputSources == null || vr.currentFrame == null || refSpace == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var inputSources = vr.currentInputSources;
|
|
||||||
var frame = vr.currentFrame;
|
|
||||||
|
|
||||||
var sourceCount:Int = untyped inputSources.length;
|
|
||||||
|
|
||||||
for (i in 0...sourceCount) {
|
|
||||||
var inputSource = untyped inputSources[i];
|
|
||||||
if (inputSource == null) continue;
|
|
||||||
|
|
||||||
var handedness = untyped inputSource.handedness; // "left", "right", or "none"
|
|
||||||
|
|
||||||
var gripSpace = untyped inputSource.gripSpace;
|
|
||||||
var targetRaySpace = untyped inputSource.targetRaySpace;
|
|
||||||
// use targetRaySpace first laser/pointer and fall back to gripSpace
|
|
||||||
var space = (targetRaySpace != null) ? targetRaySpace : gripSpace;
|
|
||||||
|
|
||||||
if (space == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pose = untyped frame.getPose(space, refSpace);
|
|
||||||
if (pose == null || pose.transform == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var transform = pose.transform;
|
|
||||||
var pos = transform.position;
|
|
||||||
var orient = transform.orientation;
|
|
||||||
|
|
||||||
if (handedness == "left") {
|
|
||||||
leftHandPosition.set(pos.x, pos.y, pos.z);
|
|
||||||
leftHandRotation.set(orient.x, orient.y, orient.z, orient.w);
|
|
||||||
leftHandActive = true;
|
|
||||||
|
|
||||||
var gamepad = untyped inputSource.gamepad;
|
|
||||||
if (gamepad != null) {
|
|
||||||
// [0]=thumbstickX [1]=thumbstickY [2]=touchpadX [3]=touchpadY
|
|
||||||
if (gamepad.axes != null && gamepad.axes.length >= 2) {
|
|
||||||
leftThumbstickX = gamepad.axes[0];
|
|
||||||
leftThumbstickY = gamepad.axes[1];
|
|
||||||
}
|
|
||||||
// [0]=trigger [1]=grip [4]=X [5]=Y
|
|
||||||
if (gamepad.buttons != null) {
|
|
||||||
if (gamepad.buttons.length > 0) leftTrigger = gamepad.buttons[0].value;
|
|
||||||
if (gamepad.buttons.length > 1) leftGrip = gamepad.buttons[1].value;
|
|
||||||
if (gamepad.buttons.length > 4) leftButtonX = gamepad.buttons[4].pressed;
|
|
||||||
if (gamepad.buttons.length > 5) leftButtonY = gamepad.buttons[5].pressed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (handedness == "right") {
|
|
||||||
rightHandPosition.set(pos.x, pos.y, pos.z);
|
|
||||||
rightHandRotation.set(orient.x, orient.y, orient.z, orient.w);
|
|
||||||
rightHandActive = true;
|
|
||||||
|
|
||||||
var gamepad = untyped inputSource.gamepad;
|
|
||||||
if (gamepad != null) {
|
|
||||||
if (gamepad.axes != null && gamepad.axes.length >= 2) {
|
|
||||||
rightThumbstickX = gamepad.axes[0];
|
|
||||||
rightThumbstickY = gamepad.axes[1];
|
|
||||||
}
|
|
||||||
if (gamepad.buttons != null) {
|
|
||||||
if (gamepad.buttons.length > 0) rightTrigger = gamepad.buttons[0].value;
|
|
||||||
if (gamepad.buttons.length > 1) rightGrip = gamepad.buttons[1].value;
|
|
||||||
if (gamepad.buttons.length > 4) rightButtonA = gamepad.buttons[4].pressed;
|
|
||||||
if (gamepad.buttons.length > 5) rightButtonB = gamepad.buttons[5].pressed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
@ -20,7 +20,6 @@ class Config {
|
|||||||
var path = iron.data.Data.dataPath + "config.lnx";
|
var path = iron.data.Data.dataPath + "config.lnx";
|
||||||
var bytes = haxe.io.Bytes.ofString(haxe.Json.stringify(raw));
|
var bytes = haxe.io.Bytes.ofString(haxe.Json.stringify(raw));
|
||||||
#if kha_krom
|
#if kha_krom
|
||||||
if (iron.data.Data.dataPath == '') path = Krom.getFilesLocation() + "/config.lnx";
|
|
||||||
Krom.fileSaveBytes(path, bytes.getData());
|
Krom.fileSaveBytes(path, bytes.getData());
|
||||||
#elseif kha_kore
|
#elseif kha_kore
|
||||||
sys.io.File.saveBytes(path, bytes);
|
sys.io.File.saveBytes(path, bytes);
|
||||||
@ -44,12 +43,10 @@ typedef TConfig = {
|
|||||||
@:optional var rp_supersample: Null<Float>;
|
@:optional var rp_supersample: Null<Float>;
|
||||||
@:optional var rp_shadowmap_cube: Null<Int>; // size
|
@:optional var rp_shadowmap_cube: Null<Int>; // size
|
||||||
@:optional var rp_shadowmap_cascade: Null<Int>; // size for single cascade
|
@:optional var rp_shadowmap_cascade: Null<Int>; // size for single cascade
|
||||||
@:optional var rp_ssao: Null<Bool>;
|
|
||||||
@:optional var rp_ssgi: Null<Bool>;
|
@:optional var rp_ssgi: Null<Bool>;
|
||||||
@:optional var rp_ssr: Null<Bool>;
|
@:optional var rp_ssr: Null<Bool>;
|
||||||
@:optional var rp_ssrefr: Null<Bool>;
|
@:optional var rp_ssrefr: Null<Bool>;
|
||||||
@:optional var rp_bloom: Null<Bool>;
|
@:optional var rp_bloom: Null<Bool>;
|
||||||
@:optional var rp_chromatic_aberration: Null<Bool>;
|
|
||||||
@:optional var rp_motionblur: Null<Bool>;
|
@:optional var rp_motionblur: Null<Bool>;
|
||||||
@:optional var rp_gi: Null<Bool>; // voxelao
|
@:optional var rp_gi: Null<Bool>; // voxelao
|
||||||
@:optional var rp_dynres: Null<Bool>; // dynamic resolution scaling
|
@:optional var rp_dynres: Null<Bool>; // dynamic resolution scaling
|
||||||
|
|||||||
@ -1,99 +0,0 @@
|
|||||||
package leenkx.logicnode;
|
|
||||||
|
|
||||||
import iron.data.SceneFormat.TSceneFormat;
|
|
||||||
import iron.data.Data;
|
|
||||||
import iron.object.Object;
|
|
||||||
|
|
||||||
class AddParticleToObjectNode extends LogicNode {
|
|
||||||
|
|
||||||
public var property0: String;
|
|
||||||
|
|
||||||
public function new(tree: LogicTree) {
|
|
||||||
super(tree);
|
|
||||||
}
|
|
||||||
|
|
||||||
override function run(from: Int) {
|
|
||||||
#if lnx_particles
|
|
||||||
|
|
||||||
if (property0 == 'Scene Active'){
|
|
||||||
var objFrom: Object = inputs[1].get();
|
|
||||||
var slot: Int = inputs[2].get();
|
|
||||||
var objTo: Object = inputs[3].get();
|
|
||||||
|
|
||||||
if (objFrom == null || objTo == null) return;
|
|
||||||
|
|
||||||
var mobjFrom = cast(objFrom, iron.object.MeshObject);
|
|
||||||
|
|
||||||
var psys = mobjFrom.particleSystems != null ? mobjFrom.particleSystems[slot] :
|
|
||||||
mobjFrom.particleOwner != null && mobjFrom.particleOwner.particleSystems != null ? mobjFrom.particleOwner.particleSystems[slot] : null;
|
|
||||||
|
|
||||||
if (psys == null) return;
|
|
||||||
|
|
||||||
var mobjTo = cast(objTo, iron.object.MeshObject);
|
|
||||||
|
|
||||||
mobjTo.setupParticleSystem(iron.Scene.active.raw.name, {name: 'LnxPS', seed: 0, particle: @:privateAccess psys.r.name});
|
|
||||||
|
|
||||||
mobjTo.render_emitter = inputs[4].get();
|
|
||||||
|
|
||||||
iron.Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
|
|
||||||
if (o != null) {
|
|
||||||
var c: iron.object.MeshObject = cast o;
|
|
||||||
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
|
|
||||||
mobjTo.particleChildren.push(c);
|
|
||||||
c.particleOwner = mobjTo;
|
|
||||||
c.particleIndex = mobjTo.particleChildren.length - 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var oslot: Int = mobjTo.particleSystems.length-1;
|
|
||||||
var opsys = mobjTo.particleSystems[oslot];
|
|
||||||
@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
var sceneName: String = inputs[1].get();
|
|
||||||
var objectName: String = inputs[2].get();
|
|
||||||
var slot: Int = inputs[3].get();
|
|
||||||
|
|
||||||
var mobjTo: Object = inputs[4].get();
|
|
||||||
var mobjTo = cast(mobjTo, iron.object.MeshObject);
|
|
||||||
|
|
||||||
#if lnx_json
|
|
||||||
sceneName += ".json";
|
|
||||||
#elseif lnx_compress
|
|
||||||
sceneName += ".lz4";
|
|
||||||
#end
|
|
||||||
|
|
||||||
Data.getSceneRaw(sceneName, (rawScene: TSceneFormat) -> {
|
|
||||||
|
|
||||||
for (obj in rawScene.objects) {
|
|
||||||
if (obj.name == objectName) {
|
|
||||||
mobjTo.setupParticleSystem(sceneName, obj.particle_refs[slot]);
|
|
||||||
mobjTo.render_emitter = inputs[5].get();
|
|
||||||
|
|
||||||
iron.Scene.active.spawnObject(rawScene.particle_datas[slot].instance_object, null, function(o: Object) {
|
|
||||||
if (o != null) {
|
|
||||||
var c: iron.object.MeshObject = cast o;
|
|
||||||
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
|
|
||||||
mobjTo.particleChildren.push(c);
|
|
||||||
c.particleOwner = mobjTo;
|
|
||||||
c.particleIndex = mobjTo.particleChildren.length - 1;
|
|
||||||
}
|
|
||||||
}, true, rawScene);
|
|
||||||
|
|
||||||
var oslot: Int = mobjTo.particleSystems.length-1;
|
|
||||||
var opsys = mobjTo.particleSystems[oslot];
|
|
||||||
@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#end
|
|
||||||
|
|
||||||
runOutput(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user