Merge pull request #1826 from Naxela/lightmapper

Lightmapper
This commit is contained in:
Lubos Lenco 2020-09-01 09:43:40 +02:00 committed by GitHub
commit 2139bdfce3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
155 changed files with 7572 additions and 2291 deletions

View File

@ -19,4 +19,4 @@ jobs:
- name: Compile
run: |
cd armory_ci
nodejs_bin/node-linux64 Kha/make.js krom
nodejs_bin/node-linux64 Kha/make.js krom --shaderversion 330

View File

@ -0,0 +1,9 @@
#version 450
in vec2 texCoord;
out vec4 fragColor;
void main() {
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
gl_FragDepth = 1.0;
}

View File

@ -0,0 +1,15 @@
{
"contexts": [
{
"name": "clear_color_depth_pass",
"depth_write": true,
"compare_mode": "always",
"cull_mode": "none",
"links": [],
"texture_params": [],
"vertex_shader": "../include/pass.vert.glsl",
"fragment_shader": "clear_color_depth_pass.frag.glsl",
"color_attachments": ["_HDR"]
}
]
}

View File

@ -0,0 +1,8 @@
#version 450
in vec2 texCoord;
out vec4 fragColor;
void main() {
fragColor = vec4(0.0, 0.0, 0.0, 1.0);
}

View File

@ -0,0 +1,15 @@
{
"contexts": [
{
"name": "clear_color_pass",
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [],
"texture_params": [],
"vertex_shader": "../include/pass.vert.glsl",
"fragment_shader": "clear_color_pass.frag.glsl",
"color_attachments": ["_HDR"]
}
]
}

View File

@ -0,0 +1,8 @@
#version 450
in vec2 texCoord;
out vec4 fragColor;
void main() {
gl_FragDepth = 1.0;
}

View File

@ -0,0 +1,19 @@
{
"contexts": [
{
"name": "clear_depth_pass",
"depth_write": true,
"color_write_red": false,
"color_write_green": false,
"color_write_blue": false,
"color_write_alpha": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [],
"texture_params": [],
"vertex_shader": "../include/pass.vert.glsl",
"fragment_shader": "clear_depth_pass.frag.glsl",
"color_attachments": ["_HDR"]
}
]
}

View File

@ -18,7 +18,7 @@ void main() {
// Scale vertex attribute to [0-1] range
const vec2 madd = vec2(0.5, 0.5);
texCoord = pos.xy * madd + madd;
#ifdef HLSL
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif
@ -26,7 +26,7 @@ void main() {
// #ifdef _CPos
// NDC (at the back of cube)
// vec4 v = vec4(pos.xy, 1.0, 1.0);
// vec4 v = vec4(pos.xy, 1.0, 1.0);
// v = vec4(invVP * v);
// v.xyz /= v.w;
// viewRay = v.xyz - eye;

View File

@ -36,7 +36,7 @@ uniform vec3 eyeSnap;
uniform float envmapStrength;
#ifdef _Irr
//!uniform vec4 shirr[7];
uniform vec4 shirr[7];
#endif
#ifdef _Brdf
uniform sampler2D senvmapBrdf;
@ -165,7 +165,7 @@ out vec4 fragColor;
void main() {
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, metallic/roughness, matid
vec3 n;
n.z = 1.0 - abs(g0.x) - abs(g0.y);
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
@ -196,7 +196,7 @@ void main() {
// Envmap
#ifdef _Irr
vec3 envl = shIrradiance(n);
vec3 envl = shIrradiance(n, shirr);
#ifdef _EnvTex
envl /= PI;
#endif
@ -218,7 +218,7 @@ void main() {
#endif
envl.rgb *= albedo;
#ifdef _Rad // Indirect specular
envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5 * occspec.y;
#else
@ -236,7 +236,7 @@ void main() {
#else
vec3 voxpos = p / voxelgiHalfExtents;
#endif
#ifndef _VoxelAONoTrace
#ifdef _VoxelGITemporal
envl.rgb *= 1.0 - (traceAO(voxpos, n, voxels) * voxelBlend +
@ -245,7 +245,7 @@ void main() {
envl.rgb *= 1.0 - traceAO(voxpos, n, voxels);
#endif
#endif
#endif
fragColor.rgb = envl;
@ -259,7 +259,7 @@ void main() {
#endif
#ifdef _Emission
if (g0.a == 1.0) {
if (matid == 1) {
fragColor.rgb += g1.rgb; // materialid
albedo = vec3(0.0);
}
@ -272,7 +272,7 @@ void main() {
// for(uint step = 0; step < 400 && color.a < 0.99f; ++step) {
// vec3 point = origin + 0.005 * step * direction;
// color += (1.0f - color.a) * textureLod(voxels, point * 0.5 + 0.5, 0);
// }
// }
// fragColor.rgb += color.rgb;
// Show SSAO
@ -320,7 +320,7 @@ void main() {
fragColor.rgb += sdirect * svisibility * sunCol;
// #ifdef _Hair // Aniso
// if (g0.a == 2.0) {
// if (matid == 2) {
// const float shinyParallel = roughness;
// const float shinyPerpendicular = 0.1;
// const vec3 v = vec3(0.99146, 0.11664, 0.05832);
@ -330,7 +330,7 @@ void main() {
// #endif
#ifdef _SSS
if (g0.a == 2.0) {
if (matid == 2) {
#ifdef _CSM
int casi, casindex;
mat4 LWVP = getCascadeMat(distance(eye, p), casi, casindex);
@ -346,7 +346,7 @@ void main() {
fragColor.rgb += sampleLight(
p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0
#ifdef _ShadowMap
, 0, pointBias
, 0, pointBias, true
#endif
#ifdef _Spot
, true, spotData.x, spotData.y, spotDir
@ -363,12 +363,12 @@ void main() {
, gbufferD, invVP, eye
#endif
);
#ifdef _Spot
#ifdef _SSS
if (g0.a == 2.0) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot0, p, n, normalize(pointPos - p), lightPlane.y, shadowMapSpot[0]);
if (matid == 2) fragColor.rgb += fragColor.rgb * SSSSTransmittance(LWVPSpot0, p, n, normalize(pointPos - p), lightPlane.y, shadowMapSpot[0]);
#endif
#endif
#endif
#endif
@ -400,7 +400,7 @@ void main() {
occspec.y,
f0
#ifdef _ShadowMap
, li, lightsArray[li * 2].w // bias
, li, lightsArray[li * 2].w, true // bias
#endif
#ifdef _Spot
, li > numPoints - 1

View File

@ -240,7 +240,8 @@
}
],
"vertex_shader": "../include/pass_viewray.vert.glsl",
"fragment_shader": "deferred_light.frag.glsl"
"fragment_shader": "deferred_light.frag.glsl",
"color_attachments": ["RGBA64"]
}
]
}

View File

@ -17,7 +17,7 @@ uniform sampler2D gbuffer1;
uniform float envmapStrength;
#ifdef _Irr
//!uniform vec4 shirr[7];
uniform vec4 shirr[7];
#endif
#ifdef _Brdf
uniform sampler2D senvmapBrdf;
@ -96,7 +96,7 @@ out vec4 fragColor;
void main() {
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, metallic/roughness, depth
vec3 n;
n.z = 1.0 - abs(g0.x) - abs(g0.y);
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
@ -123,7 +123,7 @@ void main() {
// Envmap
#ifdef _Irr
vec3 envl = shIrradiance(n);
vec3 envl = shIrradiance(n, shirr);
#ifdef _EnvTex
envl /= PI;
#endif
@ -145,7 +145,7 @@ void main() {
#endif
envl.rgb *= albedo;
#ifdef _Rad // Indirect specular
envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5 * occspec.y;
#else
@ -182,7 +182,7 @@ void main() {
fragColor.rgb += sampleLight(
p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0
#ifdef _ShadowMap
, 0, pointBias
, 0, pointBias, true
#endif
#ifdef _Spot
, true, spotData.x, spotData.y, spotDir
@ -218,7 +218,7 @@ void main() {
occspec.y,
f0
#ifdef _ShadowMap
, li, lightsArray[li * 2].w // bias
, li, lightsArray[li * 2].w, true // bias
#endif
#ifdef _Spot
, li > numPoints - 1

View File

@ -159,7 +159,8 @@
}
],
"vertex_shader": "../include/pass_viewray.vert.glsl",
"fragment_shader": "deferred_light.frag.glsl"
"fragment_shader": "deferred_light.frag.glsl",
"color_attachments": ["RGBA64"]
}
]
}

View File

@ -7,7 +7,8 @@
"cull_mode": "none",
"links": [],
"vertex_shader": "../include/pass.vert.glsl",
"fragment_shader": "deferred_light.frag.glsl"
"fragment_shader": "deferred_light.frag.glsl",
"color_attachments": ["RGBA64"]
}
]
}

View File

@ -10,7 +10,7 @@ void main() {
// Scale vertex attribute to 0-1 range
const vec2 madd = vec2(0.5, 0.5);
texCoord = pos.xy * madd + madd;
#ifdef HLSL
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif

View File

@ -14,7 +14,7 @@ void main() {
// Scale vertex attribute to [0-1] range
const vec2 madd = vec2(0.5, 0.5);
texCoord = pos.xy * madd + madd;
#ifdef HLSL
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif

View File

@ -13,14 +13,14 @@ void main() {
// Scale vertex attribute to [0-1] range
const vec2 madd = vec2(0.5, 0.5);
texCoord = pos.xy * madd + madd;
#ifdef HLSL
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif
gl_Position = vec4(pos.xy, 0.0, 1.0);
// NDC (at the back of cube)
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
v = vec4(invP * v);
viewRay = vec3(v.xy / v.z, 1.0);
}

View File

@ -18,7 +18,7 @@ in vec3 viewRay;
out vec4 fragColor;
vec2 getVelocity(vec2 coord, float depth) {
#ifdef HLSL
#ifdef _InvY
coord.y = 1.0 - coord.y;
#endif
vec4 currentPos = vec4(coord.xy * 2.0 - 1.0, depth, 1.0);
@ -26,7 +26,7 @@ vec2 getVelocity(vec2 coord, float depth) {
vec4 previousPos = prevVP * worldPos;
previousPos /= previousPos.w;
vec2 velocity = (currentPos - previousPos).xy / 40.0;
#ifdef HLSL
#ifdef _InvY
velocity.y = -velocity.y;
#endif
return velocity;
@ -34,7 +34,7 @@ vec2 getVelocity(vec2 coord, float depth) {
void main() {
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
float depth = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
if (depth == 1.0) {
return;
@ -42,7 +42,7 @@ void main() {
float blurScale = motionBlurIntensity * frameScale;
vec2 velocity = getVelocity(texCoord, depth) * blurScale;
vec2 offset = texCoord;
int processed = 1;
for(int i = 0; i < 8; ++i) {

View File

@ -14,11 +14,11 @@ out vec4 fragColor;
void main() {
vec2 velocity = textureLod(sveloc, texCoord, 0.0).rg * motionBlurIntensity * frameScale;
#ifdef HLSL
#ifdef _InvY
velocity.y = -velocity.y;
#endif
fragColor.rgb = textureLod(tex, texCoord, 0.0).rgb;
// float speed = length(velocity / texStep);

View File

@ -17,7 +17,7 @@ out vec4 fragColor;
void main() {
vec2 texCoord = wvpposition.xy / wvpposition.w;
texCoord = texCoord * 0.5 + 0.5;
#ifdef HLSL
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif
@ -46,7 +46,7 @@ void main() {
vec3 v = wp - eye;
vec3 r = reflect(v, n);
#ifdef HLSL
#ifdef _InvY
r.y = -r.y;
#endif
float intensity = clamp((1.0 - roughness) * dot(wp - probep, n), 0.0, 1.0);

View File

@ -17,7 +17,7 @@ out vec4 fragColor;
void main() {
vec2 texCoord = wvpposition.xy / wvpposition.w;
texCoord = texCoord * 0.5 + 0.5;
#ifdef HLSL
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif
@ -39,7 +39,7 @@ void main() {
vec3 wp = getPos2(invVP, depth, texCoord);
vec4 pp = probeVP * vec4(wp.xyz, 1.0);
vec2 tc = (pp.xy / pp.w) * 0.5 + 0.5;
#ifdef HLSL
#ifdef _InvY
tc.y = 1.0 - tc.y;
#endif

View File

@ -1,5 +1,6 @@
#version 450
#include "compiled.inc"
#define SMAA_MAX_SEARCH_STEPS_DIAG 8
#define SMAA_AREATEX_MAX_DISTANCE 16
#define SMAA_AREATEX_MAX_DISTANCE_DIAG 20
@ -33,7 +34,7 @@ out vec4 fragColor;
vec2 cdw_end;
vec4 textureLodA(sampler2D tex, vec2 coord, float lod) {
#ifdef HLSL
#ifdef _InvY
coord.y = 1.0 - coord.y;
#endif
return textureLod(tex, coord, lod);
@ -104,7 +105,7 @@ vec2 SMAASearchDiag2(vec2 texcoord, vec2 dir) {
return coord.zw;
}
/**
/**
* Similar to SMAAArea, this calculates the area corresponding to a certain
* diagonal distance and crossing edges 'e'.
*/
@ -147,7 +148,7 @@ vec2 SMAACalculateDiagWeights(vec2 texcoord, vec2 e, vec4 subsampleIndices) {
// Fetch the crossing edges:
vec4 coords = mad(vec4(-d.x + 0.25, d.x, d.y, -d.y - 0.25), screenSizeInv.xyxy, texcoord.xyxy);
vec4 c;
c.xy = SMAASampleLevelZeroOffset(edgesTex, coords.xy, ivec2(-1, 0)).rg;
c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, ivec2( 1, 0)).rg;
c.yxwz = SMAADecodeDiagBilinearAccess(c.xyzw);
@ -172,7 +173,7 @@ vec2 SMAACalculateDiagWeights(vec2 texcoord, vec2 e, vec4 subsampleIndices) {
d.yw = SMAASearchDiag2(texcoord, vec2(1.0, 1.0)/*, cdw_end*/);
float dadd = cdw_end.y > 0.9 ? 1.0 : 0.0;
d.y += dadd;
}
}
else {
d.yw = vec2(0.0, 0.0);
}
@ -207,7 +208,7 @@ vec2 SMAACalculateDiagWeights(vec2 texcoord, vec2 e, vec4 subsampleIndices) {
/**
* This allows to determine how much length should we add in the last step
* of the searches. It takes the bilinearly interpolated edge (see
* of the searches. It takes the bilinearly interpolated edge (see
* @PSEUDO_GATHER4), and adds 0, 1 or 2, depending on which edges and
* crossing edges are active.
*/
@ -244,7 +245,7 @@ float SMAASearchXLeft(vec2 texcoord, float end) {
* which edges are active from the four fetched ones.
*/
vec2 e = vec2(0.0, 1.0);
while (texcoord.x > end &&
while (texcoord.x > end &&
e.g > 0.8281 && // Is there some edge not activated?
e.r == 0.0) { // Or is there a crossing edge that breaks the line?
e = textureLodA(edgesTex, texcoord, 0.0).rg;
@ -257,20 +258,20 @@ float SMAASearchXLeft(vec2 texcoord, float end) {
float SMAASearchXRight(vec2 texcoord, float end) {
vec2 e = vec2(0.0, 1.0);
while (texcoord.x < end &&
while (texcoord.x < end &&
e.g > 0.8281 && // Is there some edge not activated?
e.r == 0.0) { // Or is there a crossing edge that breaks the line?
e = textureLodA(edgesTex, texcoord, 0.0).rg;
texcoord = mad(vec2(2.0, 0.0), screenSizeInv.xy, texcoord);
}
float offset = mad(-(255.0 / 127.0), SMAASearchLength(e, 0.5), 3.25);
return mad(-screenSizeInv.x, offset, texcoord.x);
}
float SMAASearchYUp(vec2 texcoord, float end) {
vec2 e = vec2(1.0, 0.0);
while (texcoord.y > end &&
while (texcoord.y > end &&
e.r > 0.8281 && // Is there some edge not activated?
e.g == 0.0) { // Or is there a crossing edge that breaks the line?
e = textureLodA(edgesTex, texcoord, 0.0).rg;
@ -282,7 +283,7 @@ float SMAASearchYUp(vec2 texcoord, float end) {
float SMAASearchYDown(vec2 texcoord, float end) {
vec2 e = vec2(1.0, 0.0);
while (texcoord.y < end &&
while (texcoord.y < end &&
e.r > 0.8281 && // Is there some edge not activated?
e.g == 0.0) { // Or is there a crossing edge that breaks the line?
e = textureLodA(edgesTex, texcoord, 0.0).rg;
@ -292,14 +293,14 @@ float SMAASearchYDown(vec2 texcoord, float end) {
return mad(-screenSizeInv.y, offset, texcoord.y);
}
/**
/**
* Ok, we have the distance and both crossing edges. So, what are the areas
* at each side of current edge?
*/
vec2 SMAAArea(vec2 dist, float e1, float e2, float offset) {
// Rounding prevents precision errors of bilinear filtering:
vec2 texcoord = mad(vec2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE), round(4.0 * vec2(e1, e2)), dist);
// We do a scale and bias for mapping to texel space:
texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE);
@ -363,7 +364,7 @@ vec4 SMAABlendingWeightCalculationPS(vec2 texcoord, vec2 pixcoord,
// one of the boundaries is enough.
weights.rg = SMAACalculateDiagWeights(texcoord, e, subsampleIndices);
// We give priority to diagonals, so if we find a diagonal we skip
// We give priority to diagonals, so if we find a diagonal we skip
// horizontal/vertical processing.
//SMAA_BRANCH
if (weights.r == -weights.g) { // weights.r + weights.g == 0.0
@ -433,7 +434,7 @@ vec4 SMAABlendingWeightCalculationPS(vec2 texcoord, vec2 pixcoord,
// We want the distances to be in pixel units:
d = abs(round(mad(screenSize.yy, d, -pixcoord.yy)));
// SMAAArea below needs a sqrt, as the areas texture is compressed
// SMAAArea below needs a sqrt, as the areas texture is compressed
// quadratically:
vec2 sqrt_d = sqrt(d);

View File

@ -11,7 +11,7 @@ out vec4 offset0;
out vec4 offset1;
out vec4 offset2;
#ifdef HLSL
#ifdef _InvY
#define V_DIR(v) -(v)
#else
#define V_DIR(v) v
@ -21,7 +21,7 @@ void main() {
// Scale vertex attribute to [0-1] range
const vec2 madd = vec2(0.5, 0.5);
texCoord = pos.xy * madd + madd;
#ifdef HLSL
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif

View File

@ -18,7 +18,7 @@ out vec4 fragColor;
// Neighborhood Blending Pixel Shader (Third Pass)
vec4 textureLodA(sampler2D tex, vec2 coords, float lod) {
#ifdef HLSL
#ifdef _InvY
coords.y = 1.0 - coords.y;
#endif
return textureLod(tex, coords, lod);
@ -49,7 +49,7 @@ vec4 SMAANeighborhoodBlendingPS(vec2 texcoord, vec4 offset) {
// Calculate the blending offsets:
vec4 blendingOffset = vec4(0.0, a.y, 0.0, a.w);
vec2 blendingWeight = a.yw;
if (h) {
blendingOffset.x = a.x;
blendingOffset.y = 0.0;
@ -58,11 +58,11 @@ vec4 SMAANeighborhoodBlendingPS(vec2 texcoord, vec4 offset) {
blendingWeight.x = a.x;
blendingWeight.y = a.z;
}
blendingWeight /= dot(blendingWeight, vec2(1.0, 1.0));
// Calculate the texture coordinates:
#ifdef HLSL
#ifdef _InvY
vec2 tc = vec2(texcoord.x, 1.0 - texcoord.y);
#else
vec2 tc = texcoord;

View File

@ -9,7 +9,7 @@ uniform vec2 screenSizeInv;
out vec2 texCoord;
out vec4 offset;
#ifdef HLSL
#ifdef _InvY
#define V_DIR(v) -(v)
#else
#define V_DIR(v) v
@ -19,7 +19,7 @@ void main() {
// Scale vertex attribute to [0-1] range
const vec2 madd = vec2(0.5, 0.5);
texCoord = pos.xy * madd + madd;
#ifdef HLSL
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif

View File

@ -37,7 +37,7 @@ vec2 getProjectedCoord(vec3 hitCoord) {
vec4 projectedCoord = P * vec4(hitCoord, 1.0);
projectedCoord.xy /= projectedCoord.w;
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
#ifdef HLSL
#ifdef _InvY
projectedCoord.y = 1.0 - projectedCoord.y;
#endif
return projectedCoord.xy;

View File

@ -29,13 +29,13 @@ vec2 getProjectedCoord(const vec3 hit) {
vec4 projectedCoord = P * vec4(hit, 1.0);
projectedCoord.xy /= projectedCoord.w;
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
#ifdef HLSL
#ifdef _InvY
projectedCoord.y = 1.0 - projectedCoord.y;
#endif
return projectedCoord.xy;
}
float getDeltaDepth(const vec3 hit) {
float getDeltaDepth(const vec3 hit) {
depth = textureLod(gbufferD, getProjectedCoord(hit), 0.0).r * 2.0 - 1.0;
vec3 viewPos = getPosView(viewRay, depth, cameraProj);
return viewPos.z - hit.z;
@ -79,7 +79,7 @@ void main() {
float spec = fract(textureLod(gbuffer1, texCoord, 0.0).a);
if (spec == 0.0) { fragColor.rgb = vec3(0.0); return; }
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
if (d == 1.0) { fragColor.rgb = vec3(0.0); return; }
@ -88,18 +88,18 @@ void main() {
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 viewNormal = V3 * n;
vec3 viewPos = getPosView(viewRay, d, cameraProj);
vec3 reflected = normalize(reflect(viewPos, viewNormal));
hitCoord = viewPos;
#ifdef _CPostprocess
vec3 dir = reflected * (1.0 - rand(texCoord) * PPComp10.y * roughness) * 2.0;
#else
vec3 dir = reflected * (1.0 - rand(texCoord) * ssrJitter * roughness) * 2.0;
#endif
// * max(ssrMinRayStep, -viewPos.z)
vec4 coords = rayCast(dir);

View File

@ -19,7 +19,7 @@ vec3 getPosView(const vec3 viewRay, const float depth, const vec2 cameraProj) {
return viewRay * linearDepth;
}
vec3 getPos(const vec3 eye, const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
vec3 getPos(const vec3 eye, const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
// eyeLook, viewRay should be normalized
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
float viewZDist = dot(eyeLook, viewRay);
@ -27,7 +27,7 @@ vec3 getPos(const vec3 eye, const vec3 eyeLook, const vec3 viewRay, const float
return wposition;
}
vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, const vec2 cameraProj) {
// eyeLook, viewRay should be normalized
float linearDepth = cameraProj.y / ((depth * 0.5 + 0.5) - cameraProj.x);
float viewZDist = dot(eyeLook, viewRay);
@ -35,7 +35,7 @@ vec3 getPosNoEye(const vec3 eyeLook, const vec3 viewRay, const float depth, cons
return wposition;
}
#ifdef HLSL
#if defined(HLSL) || defined(METAL)
vec3 getPos2(const mat4 invVP, const float depth, vec2 coord) {
coord.y = 1.0 - coord.y;
#else
@ -47,7 +47,7 @@ vec3 getPos2(const mat4 invVP, const float depth, const vec2 coord) {
return pos.xyz;
}
#ifdef HLSL
#if defined(HLSL) || defined(METAL)
vec3 getPosView2(const mat4 invP, const float depth, vec2 coord) {
coord.y = 1.0 - coord.y;
#else
@ -59,7 +59,7 @@ vec3 getPosView2(const mat4 invP, const float depth, const vec2 coord) {
return pos.xyz;
}
#ifdef HLSL
#if defined(HLSL) || defined(METAL)
vec3 getPos2NoEye(const vec3 eye, const mat4 invVP, const float depth, vec2 coord) {
coord.y = 1.0 - coord.y;
#else

View File

@ -70,7 +70,7 @@ uniform sampler2D sltcMag;
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap
, int index, float bias
, int index, float bias, bool receiveShadow
#endif
#ifdef _Spot
, bool isSpot, float spotA, float spotB, vec3 spotDir
@ -130,40 +130,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _LTC
#ifdef _ShadowMap
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#endif
#ifdef _Clusters
if (index == 0) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
}
else if (index == 1) {
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
}
else if (index == 2) {
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
}
else if (index == 3) {
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
}
#endif
#endif
return direct;
#endif
#ifdef _Spot
if (isSpot) {
float spotEffect = dot(spotDir, l); // lightDir
// x - cutoff, y - cutoff - exponent
if (spotEffect < spotA) {
direct *= smoothstep(spotB, spotA, spotEffect);
}
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
@ -186,6 +153,43 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
}
#endif
}
#endif
return direct;
#endif
#ifdef _Spot
if (isSpot) {
float spotEffect = dot(spotDir, l); // lightDir
// x - cutoff, y - cutoff - exponent
if (spotEffect < spotA) {
direct *= smoothstep(spotB, spotA, spotEffect);
}
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#endif
#ifdef _Clusters
if (index == 0) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
}
else if (index == 1) {
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
}
else if (index == 2) {
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
}
else if (index == 3) {
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
}
#endif
}
#endif
return direct;
}
@ -196,17 +200,19 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#endif
#ifdef _ShadowMap
#ifdef _SinglePoint
#ifndef _Spot
direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
#endif
#endif
#ifdef _Clusters
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#endif
if (receiveShadow) {
#ifdef _SinglePoint
#ifndef _Spot
direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
#endif
#endif
#ifdef _Clusters
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#endif
}
#endif
return direct;

View File

@ -33,7 +33,7 @@
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap
, int index, float bias
, int index, float bias, bool receiveShadow
#endif
#ifdef _Spot
, bool isSpot, float spotA, float spotB, vec3 spotDir
@ -60,28 +60,30 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
direct *= smoothstep(spotB, spotA, spotEffect);
}
#ifdef _ShadowMap
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#endif
#ifdef _Clusters
if (index == 0) {
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
#endif
#ifdef _Clusters
if (index == 0) {
vec4 lPos = LWVPSpot0 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], lPos.xyz / lPos.w, bias);
}
else if (index == 1) {
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
}
else if (index == 2) {
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
}
else if (index == 3) {
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
}
#endif
}
else if (index == 1) {
vec4 lPos = LWVPSpot1 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[1], lPos.xyz / lPos.w, bias);
}
else if (index == 2) {
vec4 lPos = LWVPSpot2 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[2], lPos.xyz / lPos.w, bias);
}
else if (index == 3) {
vec4 lPos = LWVPSpot3 * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[3], lPos.xyz / lPos.w, bias);
}
#endif
#endif
return direct;
}
@ -89,15 +91,17 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _ShadowMap
#ifndef _Spot
#ifdef _SinglePoint
direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
#endif
#ifdef _Clusters
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#endif
if (receiveShadow) {
#ifdef _SinglePoint
direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
#endif
#ifdef _Clusters
if (index == 0) direct *= PCFCube(shadowMapPoint[0], ld, -l, bias, lightProj, n);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], ld, -l, bias, lightProj, n);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], ld, -l, bias, lightProj, n);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], ld, -l, bias, lightProj, n);
#endif
}
#endif
#endif

41
Shaders/std/mapping.glsl Normal file
View File

@ -0,0 +1,41 @@
/*
https://github.com/JonasFolletete/glsl-triplanar-mapping
MIT License
Copyright (c) 2018 Jonas Folletête
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.
*/
vec3 blendNormal(vec3 normal) {
vec3 blending = abs(normal);
blending = normalize(max(blending, 0.00001));
blending /= vec3(blending.x + blending.y + blending.z);
return blending;
}
vec3 triplanarMapping (sampler2D ImageTexture, vec3 normal, vec3 position) {
vec3 normalBlend = blendNormal(normal);
vec3 xColor = texture(ImageTexture, position.yz).rgb;
vec3 yColor = texture(ImageTexture, position.xz).rgb;
vec3 zColor = texture(ImageTexture, position.xy).rgb;
return (xColor * normalBlend.x + yColor * normalBlend.y + zColor * normalBlend.z);
}

View File

@ -35,7 +35,7 @@ float PCFCube(samplerCubeShadow shadowMapCube, const vec3 lp, vec3 ml, const flo
const float s = shadowmapCubePcfSize; // TODO: incorrect...
float compare = lpToDepth(lp, lightProj) - bias * 1.5;
ml = ml + n * bias * 20;
#ifdef HLSL
#ifdef _InvY
ml.y = -ml.y;
#endif
float result = texture(shadowMapCube, vec4(ml, compare));
@ -105,7 +105,7 @@ float shadowTestCascade(sampler2DShadow shadowMap, const vec3 eye, const vec3 p,
int casi;
int casIndex;
mat4 LWVP = getCascadeMat(d, casi, casIndex);
vec4 lPos = LWVP * vec4(p, 1.0);
lPos.xyz /= lPos.w;

View File

@ -1,6 +1,5 @@
uniform vec4 shirr[7];
vec3 shIrradiance(const vec3 nor) {
vec3 shIrradiance(const vec3 nor, const vec4 shirr[7]) {
const float c1 = 0.429043;
const float c2 = 0.511664;
const float c3 = 0.743125;

View File

@ -9,7 +9,7 @@ vec2 getProjectedCoord(vec3 hitCoord) {
vec4 projectedCoord = VP * vec4(hitCoord, 1.0);
projectedCoord.xy /= projectedCoord.w;
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
#ifdef HLSL
#if defined(HLSL) || defined(METAL)
projectedCoord.y = 1.0 - projectedCoord.y;
#endif
return projectedCoord.xy;

View File

@ -15,12 +15,12 @@ const float SMAA_REPROJECTION_WEIGHT_SCALE = 30.0;
void main() {
vec4 current = textureLod(tex, texCoord, 0.0);
#ifdef _Veloc
// 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;
#ifdef HLSL
#ifdef _InvY
velocity.y = -velocity.y;
#endif

View File

@ -1,172 +0,0 @@
#version 450
#include "compiled.inc"
#ifdef _EnvTex
#include "std/math.glsl"
#endif
#ifdef _EnvCol
uniform vec3 backgroundCol;
#endif
#ifdef _EnvSky
uniform vec3 A;
uniform vec3 B;
uniform vec3 C;
uniform vec3 D;
uniform vec3 E;
uniform vec3 F;
uniform vec3 G;
uniform vec3 H;
uniform vec3 I;
uniform vec3 Z;
uniform vec3 hosekSunDirection;
#endif
#ifdef _EnvClouds
uniform sampler3D scloudsBase;
uniform sampler3D scloudsDetail;
uniform sampler2D scloudsMap;
uniform float time;
#endif
#ifdef _EnvTex
uniform sampler2D envmap;
#endif
#ifdef _EnvImg // Static background
uniform vec2 screenSize;
uniform sampler2D envmap;
#endif
#ifdef _EnvStr
uniform float envmapStrength;
#endif
in vec3 normal;
out vec4 fragColor;
#ifdef _EnvSky
vec3 hosekWilkie(float cos_theta, float gamma, float cos_gamma) {
vec3 chi = (1 + cos_gamma * cos_gamma) / pow(1 + H * H - 2 * cos_gamma * H, vec3(1.5));
return (1 + A * exp(B / (cos_theta + 0.01))) * (C + D * exp(E * gamma) + F * (cos_gamma * cos_gamma) + G * chi + I * sqrt(cos_theta));
}
#endif
#ifdef _EnvClouds
// GPU PRO 7 - Real-time Volumetric Cloudscapes
// https://www.guerrilla-games.com/read/the-real-time-volumetric-cloudscapes-of-horizon-zero-dawn
// https://github.com/sebh/TileableVolumeNoise
float remap(float old_val, float old_min, float old_max, float new_min, float new_max) {
return new_min + (((old_val - old_min) / (old_max - old_min)) * (new_max - new_min));
}
float getDensityHeightGradientForPoint(float height, float cloud_type) {
const vec4 stratusGrad = vec4(0.02f, 0.05f, 0.09f, 0.11f);
const vec4 stratocumulusGrad = vec4(0.02f, 0.2f, 0.48f, 0.625f);
const vec4 cumulusGrad = vec4(0.01f, 0.0625f, 0.78f, 1.0f);
float stratus = 1.0f - clamp(cloud_type * 2.0f, 0, 1);
float stratocumulus = 1.0f - abs(cloud_type - 0.5f) * 2.0f;
float cumulus = clamp(cloud_type - 0.5f, 0, 1) * 2.0f;
vec4 cloudGradient = stratusGrad * stratus + stratocumulusGrad * stratocumulus + cumulusGrad * cumulus;
return smoothstep(cloudGradient.x, cloudGradient.y, height) - smoothstep(cloudGradient.z, cloudGradient.w, height);
}
float sampleCloudDensity(vec3 p) {
float cloud_base = textureLod(scloudsBase, p, 0).r * 40; // Base noise
vec3 weather_data = textureLod(scloudsMap, p.xy, 0).rgb; // Weather map
cloud_base *= getDensityHeightGradientForPoint(p.z, weather_data.b); // Cloud type
cloud_base = remap(cloud_base, weather_data.r, 1.0, 0.0, 1.0); // Coverage
cloud_base *= weather_data.r;
float cloud_detail = textureLod(scloudsDetail, p, 0).r * 2; // Detail noise
float cloud_detail_mod = mix(cloud_detail, 1.0 - cloud_detail, clamp(p.z * 10.0, 0, 1));
cloud_base = remap(cloud_base, cloud_detail_mod * 0.2, 1.0, 0.0, 1.0);
return cloud_base;
}
float cloudRadiance(vec3 p, vec3 dir){
#ifdef _EnvSky
vec3 sun_dir = hosekSunDirection;
#else
vec3 sun_dir = vec3(0, 0, -1);
#endif
const int steps = 8;
float step_size = 0.5 / float(steps);
float d = 0.0;
p += sun_dir * step_size;
for(int i = 0; i < steps; ++i) {
d += sampleCloudDensity(p + sun_dir * float(i) * step_size);
}
return 1.0 - d;
}
vec3 traceClouds(vec3 sky, vec3 dir) {
const float step_size = 0.5 / float(cloudsSteps);
float T = 1.0;
float C = 0.0;
vec2 uv = dir.xy / dir.z * 0.4 * cloudsLower + cloudsWind * time * 0.02;
for (int i = 0; i < cloudsSteps; ++i) {
float h = float(i) / float(cloudsSteps);
vec3 p = vec3(uv * 0.04, h);
float d = sampleCloudDensity(p);
if (d > 0) {
// float radiance = cloudRadiance(p, dir);
C += T * exp(h) * d * step_size * 0.6 * cloudsPrecipitation;
T *= exp(-d * step_size);
if (T < 0.01) break;
}
uv += (dir.xy / dir.z) * step_size * cloudsUpper;
}
return vec3(C) + sky * T;
}
#endif // _EnvClouds
void main() {
#ifdef _EnvCol
fragColor.rgb = backgroundCol;
#ifdef _EnvTransp
return;
#endif
#ifdef _EnvClouds
vec3 n = normalize(normal);
#endif
#endif
#ifndef _EnvSky // Prevent case when sky radiance is enabled
#ifdef _EnvTex
vec3 n = normalize(normal);
fragColor.rgb = texture(envmap, envMapEquirect(n)).rgb * envmapStrength;
#ifdef _EnvLDR
fragColor.rgb = pow(fragColor.rgb, vec3(2.2));
#endif
#endif
#endif
#ifdef _EnvImg // Static background
// Will have to get rid of gl_FragCoord, pass tc from VS
vec2 texco = gl_FragCoord.xy / screenSize;
fragColor.rgb = texture(envmap, vec2(texco.x, 1.0 - texco.y)).rgb * envmapStrength;
#endif
#ifdef _EnvSky
vec3 n = normalize(normal);
float phi = acos(n.z);
float theta = atan(-n.y, n.x) + PI;
float cos_theta = clamp(n.z, 0.0, 1.0);
float cos_gamma = dot(n, hosekSunDirection);
float gamma_val = acos(cos_gamma);
fragColor.rgb = Z * hosekWilkie(cos_theta, gamma_val, cos_gamma) * envmapStrength;
#endif
#ifdef _EnvClouds
if (n.z > 0.0) fragColor.rgb = mix(fragColor.rgb, traceClouds(fragColor.rgb, n), clamp(n.z * 5.0, 0, 1));
#endif
#ifdef _LDR
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2));
#endif
fragColor.a = 0.0; // Mark as non-opaque
}

View File

@ -1,114 +0,0 @@
{
"contexts": [
{
"name": "world_pass",
"depth_write": false,
"compare_mode": "less",
"cull_mode": "clockwise",
"links": [
{
"name": "SMVP",
"link": "_skydomeMatrix"
},
{
"name": "backgroundCol",
"link": "_backgroundCol",
"ifdef": ["_EnvCol"]
},
{
"name": "A",
"link": "_hosekA",
"ifdef": ["_EnvSky"]
},
{
"name": "B",
"link": "_hosekB",
"ifdef": ["_EnvSky"]
},
{
"name": "C",
"link": "_hosekC",
"ifdef": ["_EnvSky"]
},
{
"name": "D",
"link": "_hosekD",
"ifdef": ["_EnvSky"]
},
{
"name": "E",
"link": "_hosekE",
"ifdef": ["_EnvSky"]
},
{
"name": "F",
"link": "_hosekF",
"ifdef": ["_EnvSky"]
},
{
"name": "G",
"link": "_hosekG",
"ifdef": ["_EnvSky"]
},
{
"name": "H",
"link": "_hosekH",
"ifdef": ["_EnvSky"]
},
{
"name": "I",
"link": "_hosekI",
"ifdef": ["_EnvSky"]
},
{
"name": "Z",
"link": "_hosekZ",
"ifdef": ["_EnvSky"]
},
{
"name": "hosekSunDirection",
"link": "_hosekSunDirection",
"ifdef": ["_EnvSky"]
},
{
"name": "time",
"link": "_time",
"ifdef": ["_EnvClouds"]
},
{
"name": "scloudsBase",
"link": "$clouds_base.raw",
"ifdef": ["_EnvClouds"]
},
{
"name": "scloudsDetail",
"link": "$clouds_detail.raw",
"ifdef": ["_EnvClouds"]
},
{
"name": "scloudsMap",
"link": "$clouds_map.png",
"ifdef": ["_EnvClouds"]
},
{
"name": "screenSize",
"link": "_screenSize",
"ifdef": ["_EnvImg"]
},
{
"name": "envmap",
"link": "_envmap",
"ifdef": ["_EnvTex", "_EnvImg"]
},
{
"name": "envmapStrength",
"link": "_envmapStrength",
"ifdef": ["_EnvStr"]
}
],
"texture_params": [],
"vertex_shader": "world_pass.vert.glsl",
"fragment_shader": "world_pass.frag.glsl"
}
]
}

View File

@ -1,14 +0,0 @@
#version 450
in vec3 pos;
in vec3 nor;
out vec3 normal;
uniform mat4 SMVP;
void main() {
normal = nor;
vec4 position = SMVP * vec4(pos, 1.0);
gl_Position = vec4(position);
}

View File

@ -2,21 +2,38 @@ package armory.logicnode;
class ArrayAddNode extends LogicNode {
var ar: Array<Dynamic>;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var ar: Array<Dynamic> = inputs[1].get();
ar = inputs[1].get();
if (ar == null) return;
if (inputs.length > 2) {
for (i in 2...inputs.length) {
// "Modify Original" == `false` -> Copy the input array
if (!inputs[3].get()) {
ar = ar.copy();
}
if (inputs.length > 4) {
for (i in 4...inputs.length) {
var value: Dynamic = inputs[i].get();
ar.push(value);
// "Unique Values" options only supports primitive data types
// for now, a custom indexOf() or contains() method would be
// required to compare values of other types
if (!inputs[2].get() || ar.indexOf(value) == -1) {
ar.push(value);
}
}
}
runOutput(0);
}
override function get(from: Int): Dynamic {
return ar;
}
}

View File

@ -1,22 +0,0 @@
package armory.logicnode;
class ArrayAddUniqueNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var ar: Array<Dynamic> = inputs[1].get();
if (ar == null) return;
if (inputs.length > 2) {
for (i in 2...inputs.length) {
var value: Dynamic = inputs[i].get();
if (ar.indexOf(value) == -1) ar.push(value);
}
}
runOutput(0);
}
}

View File

@ -3,6 +3,7 @@ package armory.logicnode;
class ArrayLoopNode extends LogicNode {
var value: Dynamic;
var index: Int;
public function new(tree: LogicTree) {
super(tree);
@ -12,8 +13,10 @@ class ArrayLoopNode extends LogicNode {
var ar: Array<Dynamic> = inputs[1].get();
if (ar == null) return;
index = -1;
for (val in ar) {
value = val;
index++;
runOutput(0);
if (tree.loopBreak) {
@ -21,10 +24,12 @@ class ArrayLoopNode extends LogicNode {
break;
}
}
runOutput(2);
runOutput(3);
}
override function get(from: Int): Dynamic {
return value;
if (from == 1)
return value;
return index;
}
}

View File

@ -12,7 +12,7 @@ class CanvasGetCheckboxNode extends LogicNode {
}
#if arm_ui
override function get(from: Int) {
override function get(from: Int): Dynamic { // Null<Bool>
if (canvas == null) canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
if (canvas == null || !canvas.ready) return null;

View File

@ -12,7 +12,7 @@ class CanvasGetPositionNode extends LogicNode {
}
#if arm_ui
override function get(from: Int) {
override function get(from: Int): Dynamic { // Null<Int>
if (canvas == null) canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
if (canvas == null || !canvas.ready) return null;

View File

@ -12,7 +12,7 @@ class CanvasGetSliderNode extends LogicNode {
}
#if arm_ui
override function get(from: Int) {
override function get(from: Int): Dynamic { // Null<Float>
if (canvas == null) canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
if (canvas == null || !canvas.ready) return null;

View File

@ -0,0 +1,42 @@
package armory.logicnode;
import iron.Scene;
import armory.trait.internal.CanvasScript;
class CanvasSetCheckBoxNode extends LogicNode {
var canvas: CanvasScript;
var element: String;
var value: Bool;
public function new(tree: LogicTree) {
super(tree);
}
#if arm_ui
function update() {
if (!canvas.ready) return;
// This Try/Catch hacks around an issue where the handles are
// not created yet, even though canvas.ready is true.
try {
canvas.getHandle(element).selected = value;
tree.removeUpdate(update);
}
catch (e: Dynamic) {}
runOutput(0);
}
override function run(from: Int) {
element = inputs[1].get();
value = inputs[2].get();
canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
// Ensure canvas is ready
tree.notifyOnUpdate(update);
update();
}
#end
}

View File

@ -18,8 +18,8 @@ class CanvasSetVisibleNode extends LogicNode {
if (!canvas.ready) return;
tree.removeUpdate(update);
if (visible == true) canvas.getElement(element).visible = true
else canvas.getElement(element).visible = false;
var element = canvas.getElement(element);
if (element != null) element.visible = this.visible;
runOutput(0);
}
override function run(from: Int) {

View File

@ -0,0 +1,35 @@
package armory.logicnode;
import iron.object.Object;
import armory.trait.physics.RigidBody;
class HasContactArrayNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object1: Object = inputs[0].get();
var objects: Array<Object> = inputs[1].get();
if (object1 == null || objects == null) return false;
#if arm_physics
var physics = armory.trait.physics.PhysicsWorld.active;
var rb1 = object1.getTrait(RigidBody);
var rbs = physics.getContacts(rb1);
if (rb1 != null && rbs != null) {
for (object2 in objects) {
var rb2 = object2.getTrait(RigidBody);
for (rb in rbs) {
if (rb == rb2) {
return true;
}
}
}
}
#end
return false;
}
}

View File

@ -0,0 +1,116 @@
package armory.logicnode;
import armory.trait.internal.CanvasScript;
import iron.Scene;
#if arm_ui
import zui.Canvas.Anchor;
#end
class OnCanvasElementNode extends LogicNode {
var canvas: CanvasScript;
var element: String;
/**
* The event type this node should react to, can be "click" or "hover".
*/
public var property0: String;
/**
* If the event type is click, this property states whether to check for
* "down", "started" or "released" events.
*/
public var property1: String;
/**
* The mouse button that this node should react to. Only used when listening
* for mouse clicks.
*/
public var property2: String;
public function new(tree: LogicTree) {
super(tree);
tree.notifyOnUpdate(update);
}
#if arm_ui
function update() {
element = inputs[0].get();
// Ensure canvas is ready
if(!Scene.active.ready) return;
canvas = Scene.active.getTrait(CanvasScript);
if (canvas == null) canvas = Scene.active.camera.getTrait(CanvasScript);
if(canvas == null) return;
if (!canvas.ready) return;
if(canvas.getElement(element) == null) return;
if(canvas.getElement(element).visible == false) return;
var mouse = iron.system.Input.getMouse();
var isEvent = false;
if (property0 == "click") {
switch (property1) {
case "down":
isEvent = mouse.down(property2);
case "started":
isEvent = mouse.started(property2);
case "released":
isEvent = mouse.released(property2);
}
}
// Hovered
else {
isEvent = true;
}
if (isEvent)
{
var canvasElem = canvas.getElement(element);
var left = canvasElem.x;
var top = canvasElem.y;
var right = left + canvasElem.width;
var bottom = top + canvasElem.height;
var anchor = canvasElem.anchor;
var cx = canvas.getCanvas().width;
var cy = canvas.getCanvas().height;
var mouseX = mouse.x;
var mouseY = mouse.y;
switch(anchor)
{
case Top:
mouseX -= cx/2 - canvasElem.width/2;
case TopRight:
mouseX -= cx - canvasElem.width;
case CenterLeft:
mouseY -= cy/2 - canvasElem.height/2;
case Anchor.Center:
mouseX -= cx/2 - canvasElem.width/2;
mouseY -= cy/2 - canvasElem.height/2;
case CenterRight:
mouseX -= cx - canvasElem.width;
mouseY -= cy/2 - canvasElem.height/2;
case BottomLeft:
mouseY -= cy - canvasElem.height;
case Bottom:
mouseX -= cx/2 - canvasElem.width/2;
mouseY -= cy - canvasElem.height;
case BottomRight:
mouseX -= cx - canvasElem.width;
mouseY -= cy - canvasElem.height;
}
if((mouseX >= left) && (mouseX <= right))
{
if((mouseY >= top) && (mouseY <= bottom))
{
runOutput(0);
}
}
}
}
#else
function update() {}
#end
}

View File

@ -26,13 +26,15 @@ class OnContactNode extends LogicNode {
#if arm_physics
var physics = armory.trait.physics.PhysicsWorld.active;
var rb1 = object1.getTrait(RigidBody);
var rbs = physics.getContacts(rb1);
if (rb1 != null && rbs != null) {
var rb2 = object2.getTrait(RigidBody);
for (rb in rbs) {
if (rb == rb2) {
contact = true;
break;
if (rb1 != null) {
var rbs = physics.getContacts(rb1);
if (rbs != null) {
var rb2 = object2.getTrait(RigidBody);
for (rb in rbs) {
if (rb == rb2) {
contact = true;
break;
}
}
}
}

View File

@ -0,0 +1,30 @@
package armory.logicnode;
import iron.object.Object;
import iron.Scene;
class PlayActionFromNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var object: Object = inputs[1].get();
var action: String = inputs[2].get();
var startFrame:Int = inputs[3].get();
var blendTime: Float = inputs[4].get();
if (object == null) return;
var animation = object.animation;
if (animation == null) animation = object.getParentArmature(object.name);
animation.play(action, function() {
runOutput(1);
},blendTime);
animation.update(startFrame*Scene.active.raw.frame_time);
runOutput(0);
}
}

View File

@ -2,16 +2,73 @@ package armory.logicnode;
class PlaySoundRawNode extends LogicNode {
/** The name of the sound */
public var property0: String;
/** Whether to loop the playback */
public var property1: Bool;
/** Retrigger */
public var property2: Bool;
/** Override sample rate */
public var property3: Bool;
/** Playback sample rate */
public var property4: Int;
var sound: kha.Sound = null;
var channel: kha.audio1.AudioChannel = null;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
iron.data.Data.getSound(property0, function(sound: kha.Sound) {
iron.system.Audio.play(sound, false);
});
runOutput(0);
switch (from) {
case Play:
if (sound == null) {
iron.data.Data.getSound(property0, function(s: kha.Sound) {
this.sound = s;
});
}
// Resume
if (channel != null) {
if (property2) channel.stop();
channel.play();
}
// Start
else if (sound != null) {
if (property3) sound.sampleRate = property4;
channel = iron.system.Audio.play(sound, property1);
}
tree.notifyOnUpdate(this.onUpdate);
runOutput(0);
case Pause:
if (channel != null) channel.pause();
tree.removeUpdate(this.onUpdate);
case Stop:
if (channel != null) channel.stop();
tree.removeUpdate(this.onUpdate);
runOutput(2);
}
}
function onUpdate() {
if (channel != null) {
// Done
if (channel.finished) {
channel = null;
runOutput(2);
}
// Running
else runOutput(1);
}
}
}
private enum abstract PlayState(Int) from Int to Int {
var Play = 0;
var Pause = 1;
var Stop = 2;
}

View File

@ -15,11 +15,11 @@ class SetRotationNode extends LogicNode {
override function run(from: Int) {
var object: Object = inputs[1].get();
if (object == null) {
return;
}
if (object == null) return;
var vec: Vec4 = inputs[2].get();
if (vec == null) return;
var w: Float = inputs[3].get();
switch (property0) {
case "Euler Angles":
object.transform.rot.fromEuler(vec.x, vec.y, vec.z);

View File

@ -13,6 +13,10 @@ class SetSceneNode extends LogicNode {
override function run(from: Int) {
var sceneName: String = inputs[1].get();
#if arm_json
sceneName += ".json";
#end
iron.Scene.setActive(sceneName, function(o: iron.object.Object) {
root = o;
runOutput(0);

View File

@ -14,6 +14,7 @@ class TraitNode extends LogicNode {
var cname = Type.resolveClass(Main.projectPackage + "." + property0);
if (cname == null) cname = Type.resolveClass(Main.projectPackage + ".node." + property0);
if (cname == null) throw 'No trait with the name "$property0" found, make sure that the trait is exported!';
value = Type.createInstance(cname, []);
return value;
}

View File

@ -22,12 +22,9 @@ class TranslateObjectNode extends LogicNode {
object.transform.buildMatrix();
}
else {
var look = object.transform.world.look().mult(vec.y);
var right = object.transform.world.right().mult(vec.x);
var up = object.transform.world.up().mult(vec.z);
object.transform.loc.add(look);
object.transform.loc.add(right);
object.transform.loc.add(up);
object.transform.move(object.transform.local.look(),vec.y);
object.transform.move(object.transform.local.up(),vec.z);
object.transform.move(object.transform.local.right(),vec.x);
object.transform.buildMatrix();
}

View File

@ -1,14 +1,10 @@
package armory.logicnode;
import iron.object.Object;
import iron.math.Vec4;
import armory.trait.physics.RigidBody;
class TranslateOnLocalAxisNode extends LogicNode {
var loc = new Vec4();
var vec = new Vec4();
public function new(tree: LogicTree) {
super(tree);
}
@ -21,21 +17,12 @@ class TranslateOnLocalAxisNode extends LogicNode {
if (object == null) return;
if (l == 1) loc.setFrom(object.transform.world.look());
else if (l == 2) loc.setFrom(object.transform.world.up());
else if (l == 3) loc.setFrom(object.transform.world.right());
if (ini) sp *= -1;
if (ini) {
loc.x = -loc.x;
loc.y = -loc.y;
loc.z = -loc.z;
}
if (l == 1) object.transform.move(object.transform.local.look(),sp);
else if (l == 2) object.transform.move(object.transform.local.up(),sp);
else if (l == 3) object.transform.move(object.transform.local.right(),sp);
vec.x = loc.x * sp;
vec.y = loc.y * sp;
vec.z = loc.z * sp;
object.transform.loc.add(vec);
object.transform.buildMatrix();
#if arm_physics

View File

@ -42,6 +42,8 @@ class VectorMathNode extends LogicNode {
f = v.length();
case "Distance":
f = v.distanceTo(v2);
case "Reflect":
v.reflect(v2);
}
if (from == 0) return v;

View File

@ -17,6 +17,7 @@ class VectorNode extends LogicNode {
}
override function get(from: Int): Dynamic {
value = new Vec4();
value.x = inputs[0].get();
value.y = inputs[1].get();
value.z = inputs[2].get();

View File

@ -41,7 +41,7 @@ class Inc {
public static function bindShadowMap() {
for (l in iron.Scene.active.lights) {
if (!l.visible || !l.data.raw.cast_shadow || l.data.raw.type != "sun") continue;
if (!l.visible || l.data.raw.type != "sun") continue;
var n = "shadowMap";
path.bindTarget(n, n);
break;
@ -109,7 +109,8 @@ class Inc {
pointIndex = 0;
spotIndex = 0;
for (l in iron.Scene.active.lights) {
if (!l.visible || !l.data.raw.cast_shadow) continue;
if (!l.visible) continue;
path.light = l;
var shadowmap = Inc.getShadowMap(l);
var faces = l.data.raw.shadowmap_cube ? 6 : 1;
@ -117,7 +118,9 @@ class Inc {
if (faces > 1) path.currentFace = i;
path.setTarget(shadowmap);
path.clearTarget(null, 1.0);
path.drawMeshes("shadowmap");
if (l.data.raw.cast_shadow) {
path.drawMeshes("shadowmap");
}
}
path.currentFace = -1;

View File

@ -1,9 +1,8 @@
package armory.renderpath;
import iron.Scene;
import iron.object.Object;
import iron.data.MaterialData;
import iron.math.Vec4;
import iron.object.Object;
class Postprocess {
@ -100,253 +99,208 @@ class Postprocess {
public static function vec3Link(object:Object, mat:MaterialData, link:String):iron.math.Vec4 {
var v:Vec4 = null;
if (link == "_globalWeight") {
switch link {
case "_globalWeight":
var ppm_index = 0;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_global_uniforms[ppm_index][0];
v.y = colorgrading_global_uniforms[ppm_index][1];
v.z = colorgrading_global_uniforms[ppm_index][2];
}
if (link == "_globalTint") {
case "_globalTint":
var ppm_index = 1;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_global_uniforms[ppm_index][0];
v.y = colorgrading_global_uniforms[ppm_index][1];
v.z = colorgrading_global_uniforms[ppm_index][2];
}
if (link == "_globalSaturation") {
case "_globalSaturation":
var ppm_index = 2;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_global_uniforms[ppm_index][0];
v.y = colorgrading_global_uniforms[ppm_index][1];
v.z = colorgrading_global_uniforms[ppm_index][2];
}
if (link == "_globalContrast") {
case "_globalContrast":
var ppm_index = 3;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_global_uniforms[ppm_index][0];
v.y = colorgrading_global_uniforms[ppm_index][1];
v.z = colorgrading_global_uniforms[ppm_index][2];
}
if (link == "_globalGamma") {
case "_globalGamma":
var ppm_index = 4;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_global_uniforms[ppm_index][0];
v.y = colorgrading_global_uniforms[ppm_index][1];
v.z = colorgrading_global_uniforms[ppm_index][2];
}
if (link == "_globalGain") {
case "_globalGain":
var ppm_index = 5;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_global_uniforms[ppm_index][0];
v.y = colorgrading_global_uniforms[ppm_index][1];
v.z = colorgrading_global_uniforms[ppm_index][2];
}
if (link == "_globalOffset") {
case "_globalOffset":
var ppm_index = 6;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_global_uniforms[ppm_index][0];
v.y = colorgrading_global_uniforms[ppm_index][1];
v.z = colorgrading_global_uniforms[ppm_index][2];
}
//Shadow ppm
if (link == "_shadowSaturation") {
case "_shadowSaturation":
var ppm_index = 0;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_shadow_uniforms[ppm_index][0];
v.y = colorgrading_shadow_uniforms[ppm_index][1];
v.z = colorgrading_shadow_uniforms[ppm_index][2];
}
if (link == "_shadowContrast") {
case "_shadowContrast":
var ppm_index = 1;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_shadow_uniforms[ppm_index][0];
v.y = colorgrading_shadow_uniforms[ppm_index][1];
v.z = colorgrading_shadow_uniforms[ppm_index][2];
}
if (link == "_shadowGamma") {
case "_shadowGamma":
var ppm_index = 2;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_shadow_uniforms[ppm_index][0];
v.y = colorgrading_shadow_uniforms[ppm_index][1];
v.z = colorgrading_shadow_uniforms[ppm_index][2];
}
if (link == "_shadowGain") {
case "_shadowGain":
var ppm_index = 3;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_shadow_uniforms[ppm_index][0];
v.y = colorgrading_shadow_uniforms[ppm_index][1];
v.z = colorgrading_shadow_uniforms[ppm_index][2];
}
if (link == "_shadowOffset") {
case "_shadowOffset":
var ppm_index = 4;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_shadow_uniforms[ppm_index][0];
v.y = colorgrading_shadow_uniforms[ppm_index][1];
v.z = colorgrading_shadow_uniforms[ppm_index][2];
}
//Midtone ppm
if (link == "_midtoneSaturation") {
case "_midtoneSaturation":
var ppm_index = 0;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_midtone_uniforms[ppm_index][0];
v.y = colorgrading_midtone_uniforms[ppm_index][1];
v.z = colorgrading_midtone_uniforms[ppm_index][2];
}
if (link == "_midtoneContrast") {
case "_midtoneContrast":
var ppm_index = 1;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_midtone_uniforms[ppm_index][0];
v.y = colorgrading_midtone_uniforms[ppm_index][1];
v.z = colorgrading_midtone_uniforms[ppm_index][2];
}
if (link == "_midtoneGamma") {
case "_midtoneGamma":
var ppm_index = 2;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_midtone_uniforms[ppm_index][0];
v.y = colorgrading_midtone_uniforms[ppm_index][1];
v.z = colorgrading_midtone_uniforms[ppm_index][2];
}
if (link == "_midtoneGain") {
case "_midtoneGain":
var ppm_index = 3;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_midtone_uniforms[ppm_index][0];
v.y = colorgrading_midtone_uniforms[ppm_index][1];
v.z = colorgrading_midtone_uniforms[ppm_index][2];
}
if (link == "_midtoneOffset") {
case "_midtoneOffset":
var ppm_index = 4;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_midtone_uniforms[ppm_index][0];
v.y = colorgrading_midtone_uniforms[ppm_index][1];
v.z = colorgrading_midtone_uniforms[ppm_index][2];
}
//Highlight ppm
if (link == "_highlightSaturation") {
case "_highlightSaturation":
var ppm_index = 0;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_highlight_uniforms[ppm_index][0];
v.y = colorgrading_highlight_uniforms[ppm_index][1];
v.z = colorgrading_highlight_uniforms[ppm_index][2];
}
if (link == "_highlightContrast") {
case "_highlightContrast":
var ppm_index = 1;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_highlight_uniforms[ppm_index][0];
v.y = colorgrading_highlight_uniforms[ppm_index][1];
v.z = colorgrading_highlight_uniforms[ppm_index][2];
}
if (link == "_highlightGamma") {
case "_highlightGamma":
var ppm_index = 2;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_highlight_uniforms[ppm_index][0];
v.y = colorgrading_highlight_uniforms[ppm_index][1];
v.z = colorgrading_highlight_uniforms[ppm_index][2];
}
if (link == "_highlightGain") {
case "_highlightGain":
var ppm_index = 3;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_highlight_uniforms[ppm_index][0];
v.y = colorgrading_highlight_uniforms[ppm_index][1];
v.z = colorgrading_highlight_uniforms[ppm_index][2];
}
if (link == "_highlightOffset") {
case "_highlightOffset":
var ppm_index = 4;
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_highlight_uniforms[ppm_index][0];
v.y = colorgrading_highlight_uniforms[ppm_index][1];
v.z = colorgrading_highlight_uniforms[ppm_index][2];
}
//Postprocess Components
if (link == "_PPComp1") {
case "_PPComp1":
v = iron.object.Uniforms.helpVec;
v.x = camera_uniforms[0]; //F-Number
v.y = camera_uniforms[1]; //Shutter
v.z = camera_uniforms[2]; //ISO
}
if (link == "_PPComp2") {
case "_PPComp2":
v = iron.object.Uniforms.helpVec;
v.x = camera_uniforms[3]; //EC
v.y = camera_uniforms[4]; //Lens Distortion
v.z = camera_uniforms[5]; //DOF Autofocus
}
if (link == "_PPComp3") {
case "_PPComp3":
v = iron.object.Uniforms.helpVec;
v.x = camera_uniforms[6]; //Distance
v.y = camera_uniforms[7]; //Focal Length
v.z = camera_uniforms[8]; //F-Stop
}
if (link == "_PPComp4") {
case "_PPComp4":
v = iron.object.Uniforms.helpVec;
v.x = Std.int(camera_uniforms[9]); //Tonemapping
v.y = camera_uniforms[10]; //Film Grain
v.z = tonemapper_uniforms[0]; //Slope
}
if (link == "_PPComp5") {
case "_PPComp5":
v = iron.object.Uniforms.helpVec;
v.x = tonemapper_uniforms[1]; //Toe
v.y = tonemapper_uniforms[2]; //Shoulder
v.z = tonemapper_uniforms[3]; //Black Clip
}
if (link == "_PPComp6") {
case "_PPComp6":
v = iron.object.Uniforms.helpVec;
v.x = tonemapper_uniforms[4]; //White Clip
v.y = lenstexture_uniforms[0]; //Center Min
v.z = lenstexture_uniforms[1]; //Center Max
}
if (link == "_PPComp7") {
case "_PPComp7":
v = iron.object.Uniforms.helpVec;
v.x = lenstexture_uniforms[2]; //Lum min
v.y = lenstexture_uniforms[3]; //Lum max
v.z = lenstexture_uniforms[4]; //Expo
}
if (link == "_PPComp8") {
case "_PPComp8":
v = iron.object.Uniforms.helpVec;
v.x = colorgrading_global_uniforms[7][0]; //LUT R
v.y = colorgrading_global_uniforms[7][1]; //LUT G
v.z = colorgrading_global_uniforms[7][2]; //LUT B
}
if (link == "_PPComp9") {
case "_PPComp9":
v = iron.object.Uniforms.helpVec;
v.x = ssr_uniforms[0]; //Step
v.y = ssr_uniforms[1]; //StepMin
v.z = ssr_uniforms[2]; //Search
}
if (link == "_PPComp10") {
case "_PPComp10":
v = iron.object.Uniforms.helpVec;
v.x = ssr_uniforms[3]; //Falloff
v.y = ssr_uniforms[4]; //Jitter
v.z = bloom_uniforms[0]; //Bloom Threshold
}
if (link == "_PPComp11") {
case "_PPComp11":
v = iron.object.Uniforms.helpVec;
v.x = bloom_uniforms[1]; //Bloom Strength
v.y = bloom_uniforms[2]; //Bloom Radius
v.z = ssao_uniforms[0]; //SSAO Strength
}
if (link == "_PPComp12") {
case "_PPComp12":
v = iron.object.Uniforms.helpVec;
v.x = ssao_uniforms[1]; //SSAO Radius
v.y = ssao_uniforms[2]; //SSAO Max Steps
v.z = 0;
}
if(link == "_PPComp13") {
case "_PPComp13":
v = iron.object.Uniforms.helpVec;
v.x = chromatic_aberration_uniforms[0]; //CA Strength
v.y = chromatic_aberration_uniforms[1]; //CA Samples
@ -354,13 +308,10 @@ class Postprocess {
}
return v;
}
public static function init() {
iron.object.Uniforms.externalVec3Links.push(vec3Link);
}
}

View File

@ -1,6 +1,7 @@
package armory.renderpath;
import iron.RenderPath;
import iron.Scene;
class RenderPathDeferred {
@ -37,9 +38,12 @@ class RenderPathDeferred {
path = _path;
#if (rp_background == "World")
#if kha_metal
{
path.loadShader("shader_datas/world_pass/world_pass");
path.loadShader("shader_datas/clear_color_depth_pass/clear_color_depth_pass");
path.loadShader("shader_datas/clear_color_pass/clear_color_pass");
path.loadShader("shader_datas/clear_depth_pass/clear_depth_pass");
path.clearShader = "shader_datas/clear_color_depth_pass/clear_color_depth_pass";
}
#end
@ -639,8 +643,10 @@ class RenderPathDeferred {
#if (rp_background == "World")
{
path.setTarget("tex"); // Re-binds depth
path.drawSkydome("shader_datas/world_pass/world_pass");
if (Scene.active.raw.world_ref != null) {
path.setTarget("tex"); // Re-binds depth
path.drawSkydome("shader_datas/World_" + Scene.active.raw.world_ref + "/World_" + Scene.active.raw.world_ref);
}
}
#end

View File

@ -1,6 +1,7 @@
package armory.renderpath;
import iron.RenderPath;
import iron.Scene;
class RenderPathForward {
@ -34,8 +35,10 @@ class RenderPathForward {
#if (rp_background == "World")
{
RenderPathCreator.setTargetMeshes();
path.drawSkydome("shader_datas/world_pass/world_pass");
if (Scene.active.raw.world_ref != null) {
RenderPathCreator.setTargetMeshes();
path.drawSkydome("shader_datas/World_" + Scene.active.raw.world_ref + "/World_" + Scene.active.raw.world_ref);
}
}
#end
@ -62,9 +65,12 @@ class RenderPathForward {
path = _path;
#if (rp_background == "World")
#if kha_metal
{
path.loadShader("shader_datas/world_pass/world_pass");
path.loadShader("shader_datas/clear_color_depth_pass/clear_color_depth_pass");
path.loadShader("shader_datas/clear_color_pass/clear_color_pass");
path.loadShader("shader_datas/clear_depth_pass/clear_depth_pass");
path.clearShader = "shader_datas/clear_color_depth_pass/clear_color_depth_pass";
}
#end

View File

@ -4,8 +4,6 @@ import kha.WindowOptions;
class Starter {
static var tasks: Int;
#if arm_loadscreen
public static var drawLoading: kha.graphics2.Graphics->Int->Int->Void = null;
public static var numAssets: Int;
@ -13,6 +11,8 @@ class Starter {
public static function main(scene: String, mode: Int, resize: Bool, min: Bool, max: Bool, w: Int, h: Int, msaa: Int, vsync: Bool, getRenderPath: Void->iron.RenderPath) {
var tasks = 0;
function start() {
if (tasks > 0) return;
@ -76,20 +76,17 @@ class Starter {
#if (js && arm_bullet)
function loadLibAmmo(name: String) {
kha.Assets.loadBlobFromPath(name, function(b: kha.Blob) {
var print = function(s:String) { trace(s); };
var loaded = function() { tasks--; start(); };
untyped __js__("(1, eval)({0})", b.toString());
js.Syntax.code("(1,eval)({0})", b.toString());
#if kha_krom
var instantiateWasm = function(imports, successCallback) {
var wasmbin = Krom.loadBlob("ammo.wasm.wasm");
var module = new js.lib.webassembly.Module(wasmbin);
var inst = new js.lib.webassembly.Instance(module, imports);
js.Syntax.code("Ammo({print:function(s){haxe.Log.trace(s);},instantiateWasm:function(imports,successCallback) {
var wasmbin = Krom.loadBlob('ammo.wasm.wasm');
var module = new WebAssembly.Module(wasmbin);
var inst = new WebAssembly.Instance(module,imports);
successCallback(inst);
return inst.exports;
};
untyped __js__("Ammo({print:print, instantiateWasm:instantiateWasm}).then(loaded)");
}}).then(function(){ tasks--; start();})");
#else
untyped __js__("Ammo({print:print}).then(loaded)");
js.Syntax.code("Ammo({print:function(s){haxe.Log.trace(s);}}).then(function(){ tasks--; start();})");
#end
});
}
@ -98,7 +95,7 @@ class Starter {
#if (js && arm_navigation)
function loadLib(name: String) {
kha.Assets.loadBlobFromPath(name, function(b: kha.Blob) {
untyped __js__("(1, eval)({0})", b.toString());
js.Syntax.code("(1, eval)({0})", b.toString());
tasks--;
start();
});

View File

@ -103,7 +103,7 @@ class PhysicsDrag extends Trait {
dir.setZ(dir.z() * pickDist);
var newPivotB = new bullet.Bt.Vector3(rayFrom.x() + dir.x(), rayFrom.y() + dir.y(), rayFrom.z() + dir.z());
#if js
#if (js || hl)
pickConstraint.getFrameOffsetA().setOrigin(newPivotB);
#elseif cpp
pickConstraint.setFrameOffsetAOrigin(newPivotB);

View File

@ -9,7 +9,7 @@ import iron.math.Vec4;
class WalkNavigation extends Trait {
public static var enabled = true;
static inline var speed = 5.0;
var speed = 5.0;
var dir = new Vec4();
var xvec = new Vec4();
var yvec = new Vec4();
@ -111,6 +111,13 @@ class WalkNavigation extends Trait {
if (ease < 0.0) ease = 0.0;
}
if (mouse.wheelDelta < 0) {
speed *= 1.1;
} else if (mouse.wheelDelta > 0) {
speed *= 0.9;
if (speed < 0.5) speed = 0.5;
}
var d = Time.delta * speed * fast * ease;
if (d > 0.0) camera.transform.move(dir, d);

View File

@ -60,7 +60,8 @@ class CanvasScript extends Trait {
notifyOnRender2D(function(g: kha.graphics2.Graphics) {
if (canvas == null) return;
setCanvasDimensions(kha.System.windowWidth(), kha.System.windowHeight());
var events = Canvas.draw(cui, canvas, g);
for (e in events) {
@ -103,6 +104,14 @@ class CanvasScript extends Trait {
return canvas;
}
/**
* Set UI scale factor.
* @param factor Scale factor.
*/
public function setUiScale(factor:Float) {
cui.setScale(factor);
}
/**
* Set visibility of canvas
* @param visible Whether canvas should be visible or not
@ -110,7 +119,16 @@ class CanvasScript extends Trait {
public function setCanvasVisibility(visible: Bool){
for (e in canvas.elements) e.visible = visible;
}
/**
* Set dimensions of canvas
* @param x Width
* @param y Height
*/
public function setCanvasDimensions(x: Int, y: Int){
canvas.width = x;
canvas.height = y;
}
/**
* Set font size of the canvas
* @param fontSize Size of font to be setted

View File

@ -118,7 +118,7 @@ class DebugConsole extends Trait {
static var haxeTrace: Dynamic->haxe.PosInfos->Void = null;
static var lastTraces: Array<String> = [""];
static function consoleTrace(v: Dynamic, ?inf: haxe.PosInfos) {
lastTraces.unshift(Std.string(v));
lastTraces.unshift(haxe.Log.formatOutput(v,inf));
if (lastTraces.length > 10) lastTraces.pop();
haxeTrace(v, inf);
}
@ -167,7 +167,7 @@ class DebugConsole extends Trait {
if (currentObject.children.length > 0) {
ui.row([1 / 13, 12 / 13]);
b = ui.panel(listHandle.nest(lineCounter, {selected: true}), "", true);
b = ui.panel(listHandle.nest(lineCounter, {selected: true}), "", true, false, false);
ui.text(currentObject.name);
}
else {
@ -175,7 +175,7 @@ class DebugConsole extends Trait {
// Draw line that shows parent relations
ui.g.color = ui.t.ACCENT_COL;
ui.g.drawLine(ui._x - 16, ui._y + ui.ELEMENT_H() / 2, ui._x, ui._y + ui.ELEMENT_H() / 2);
ui.g.drawLine(ui._x - 10, ui._y + ui.ELEMENT_H() / 2, ui._x, ui._y + ui.ELEMENT_H() / 2);
ui.g.color = 0xffffffff;
ui.text(currentObject.name);
@ -352,8 +352,13 @@ class DebugConsole extends Trait {
if (selectedObject.name == "Scene") {
selectedType = "(Scene)";
var p = iron.Scene.active.world.probe;
p.raw.strength = ui.slider(Id.handle({value: p.raw.strength}), "Env Strength", 0.0, 5.0, true);
if (iron.Scene.active.world != null) {
var p = iron.Scene.active.world.probe;
p.raw.strength = ui.slider(Id.handle({value: p.raw.strength}), "Env Strength", 0.0, 5.0, true);
}
else {
ui.text("This scene has no world data to edit.");
}
}
else if (Std.is(selectedObject, iron.object.LightObject)) {
selectedType = "(Light)";

View File

@ -327,7 +327,7 @@ class PhysicsWorld extends Trait {
#if js
rayCallback.set_m_collisionFilterGroup(group);
rayCallback.set_m_collisionFilterMask(mask);
#elseif cpp
#elseif (cpp || hl)
rayCallback.m_collisionFilterGroup = group;
rayCallback.m_collisionFilterMask = mask;
#end
@ -348,7 +348,7 @@ class PhysicsWorld extends Trait {
hitNormalWorld.set(norm.x(), norm.y(), norm.z());
rb = rbMap.get(untyped body.userIndex);
hitInfo = new Hit(rb, hitPointWorld, hitNormalWorld);
#elseif cpp
#elseif (cpp || hl)
var hit = rayCallback.m_hitPointWorld;
hitPointWorld.set(hit.x(), hit.y(), hit.z());
var norm = rayCallback.m_hitNormalWorld;

View File

@ -41,6 +41,7 @@ class RigidBody extends iron.Trait {
var currentScaleX: Float;
var currentScaleY: Float;
var currentScaleZ: Float;
var meshInterface: bullet.Bt.TriangleMesh;
public var body: bullet.Bt.RigidBody = null;
public var motionState: bullet.Bt.MotionState;
@ -95,7 +96,7 @@ class RigidBody extends iron.Trait {
this.mask = mask;
if (params == null) params = [0.04, 0.1, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0];
if (flags == null) flags = [false, false, false];
if (flags == null) flags = [false, false, false, false];
this.linearDamping = params[0];
this.angularDamping = params[1];
@ -166,7 +167,7 @@ class RigidBody extends iron.Trait {
btshape = caps;
}
else if (shape == Shape.Mesh) {
var meshInterface = fillTriangleMesh(transform.scale);
meshInterface = fillTriangleMesh(transform.scale);
if (mass > 0) {
var shapeGImpact = new bullet.Bt.GImpactMeshShape(meshInterface);
shapeGImpact.updateBound();
@ -564,11 +565,25 @@ class RigidBody extends iron.Trait {
var data = cast(object, MeshObject).data;
var i = usersCache.get(data) - 1;
usersCache.set(data, i);
if(shape == Shape.Mesh) deleteShape();
if (i <= 0) {
deleteShape();
shape == Shape.ConvexHull ?
convexHullCache.remove(data) :
if(shape == Shape.ConvexHull)
{
deleteShape();
convexHullCache.remove(data);
}
else
{
triangleMeshCache.remove(data);
if(meshInterface != null)
{
#if js
bullet.Bt.Ammo.destroy(meshInterface);
#else
meshInterface.delete();
#end
}
}
}
}
else deleteShape();

View File

@ -2,6 +2,8 @@ import shutil
import os
import stat
import bpy
import arm.log as log
import arm.utils
assets = []
@ -48,20 +50,26 @@ def reset():
shader_cons['voxel_frag'] = []
shader_cons['voxel_geom'] = []
def add(file):
def add(asset_file):
global assets
if file in assets:
# Asset already exists, do nothing
if asset_file in assets:
return
base = os.path.basename(file)
asset_file_base = os.path.basename(asset_file)
for f in assets:
if f.endswith(base):
print('Armory Warning: Asset name "{0}" already exists, skipping'.format(base))
f_file_base = os.path.basename(f)
if f_file_base == asset_file_base:
log.warn(f'Armory Warning: Asset name "{asset_file_base}" already exists, skipping')
return
assets.append(file)
assets.append(asset_file)
# Reserved file name
for f in reserved_names:
if f in file:
print('Armory Warning: File "{0}" contains reserved keyword, this will break C++ builds!'.format(file))
if f in asset_file:
log.warn(f'Armory Warning: File "{asset_file}" contains reserved keyword, this will break C++ builds!')
def add_khafile_def(d):
global khafile_defs

File diff suppressed because it is too large Load Diff

View File

@ -171,7 +171,7 @@ def export_mesh_data(self, exportMesh, bobject, o, has_armature=False):
o['scale_pos'] = 1.0
if has_armature: # Allow up to 2x bigger bounds for skinned mesh
o['scale_pos'] *= 2.0
scale_pos = o['scale_pos']
invscale_pos = (1 / scale_pos) * 32767
@ -265,16 +265,16 @@ def export_mesh_data(self, exportMesh, bobject, o, has_armature=False):
# Output
o['vertex_arrays'] = []
o['vertex_arrays'].append({ 'attrib': 'pos', 'values': pdata })
o['vertex_arrays'].append({ 'attrib': 'nor', 'values': ndata })
o['vertex_arrays'].append({ 'attrib': 'pos', 'values': pdata, 'data': 'short4norm' })
o['vertex_arrays'].append({ 'attrib': 'nor', 'values': ndata, 'data': 'short2norm' })
if has_tex:
o['vertex_arrays'].append({ 'attrib': 'tex', 'values': t0data })
o['vertex_arrays'].append({ 'attrib': 'tex', 'values': t0data, 'data': 'short2norm' })
if has_tex1:
o['vertex_arrays'].append({ 'attrib': 'tex1', 'values': t1data })
o['vertex_arrays'].append({ 'attrib': 'tex1', 'values': t1data, 'data': 'short2norm' })
if has_col:
o['vertex_arrays'].append({ 'attrib': 'col', 'values': cdata })
o['vertex_arrays'].append({ 'attrib': 'col', 'values': cdata, 'data': 'short4norm', 'padding': 1 })
if has_tang:
o['vertex_arrays'].append({ 'attrib': 'tang', 'values': tangdata })
o['vertex_arrays'].append({ 'attrib': 'tang', 'values': tangdata, 'data': 'short4norm', 'padding': 1 })
return vert_list
@ -348,7 +348,7 @@ def export_skin(self, bobject, armature, vert_list, o):
bone_count = 4
bone_values.sort(reverse=True)
bone_values = bone_values[:4]
bone_count_array[index] = bone_count
for bv in bone_values:
bone_weight_array[count] = bv[0] * 32767

View File

@ -1,12 +1,21 @@
import bpy
import arm.props_ui as props_ui
import arm.utils
arm_keymaps = []
def register():
wm = bpy.context.window_manager
km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW")
addon_keyconfig = wm.keyconfigs.addon
# Keyconfigs are not available in background mode. If the keyconfig
# was not found despite running _not_ in background mode, a warning
# is printed
if addon_keyconfig is None:
if not bpy.app.background:
print("Armory warning: no keyconfig path found")
return
km = addon_keyconfig.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW")
km.keymap_items.new(props_ui.ArmoryPlayButton.bl_idname, type='F5', value='PRESS')
arm_keymaps.append(km)

View File

@ -34,6 +34,12 @@ def parse_context(c, sres, asset, defs, vert=None, frag=None):
if con['tesseval_shader'] not in asset:
asset.append(con['tesseval_shader'])
if 'color_attachments' in c:
con['color_attachments'] = c['color_attachments']
for i in range(len(con['color_attachments'])):
if con['color_attachments'][i] == '_HDR':
con['color_attachments'][i] = 'RGBA32' if '_LDR' in defs else 'RGBA64'
# Params
params = ['depth_write', 'compare_mode', 'cull_mode', \
'blend_source', 'blend_destination', 'blend_operation', \
@ -65,7 +71,7 @@ def parse_context(c, sres, asset, defs, vert=None, frag=None):
with open(c['tesscontrol_shader']) as f:
tesc = f.read().splitlines()
parse_shader(sres, c, con, defs, tesc, False)
if 'tesseval_shader' in c:
with open(c['tesseval_shader']) as f:
tese = f.read().splitlines()
@ -76,12 +82,12 @@ def parse_shader(sres, c, con, defs, lines, parse_attributes):
skip_else = False
vertex_elements_parsed = False
vertex_elements_parsing = False
stack = []
if parse_attributes == False:
vertex_elements_parsed = True
for line in lines:
line = line.lstrip()

View File

@ -0,0 +1 @@
__all__ = ('Operators', 'Properties', 'Preferences', 'Utility', 'Keymap')

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,7 @@
from . import keymap
def register():
keymap.register()
def unregister():
keymap.unregister()

View File

@ -0,0 +1,21 @@
import bpy
#from .. operators import build
#from .. operators import clean
tlm_keymaps = []
def register():
pass
# winman = bpy.context.window_manager
# keyman = winman.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY', region_type="WINDOW")
# keyman.keymap_items.new(build.TLM_BuildLightmaps.bl_idname, type='F6', value='PRESS')
# keyman.keymap_items.new(clean.TLM_CleanLightmaps.bl_idname, type='F7', value='PRESS')
# tlm_keymaps.append(keyman)
def unregister():
pass
# winman = bpy.context.window_manager
# for keyman in tlm_keymaps:
# winman.keyconfigs.addon.keymaps.remove(keyman)
# del tlm_keymaps[:]

View File

@ -0,0 +1,21 @@
import bpy
from bpy.utils import register_class, unregister_class
from . import tlm, installopencv
classes = [
tlm.TLM_BuildLightmaps,
tlm.TLM_CleanLightmaps,
tlm.TLM_ExploreLightmaps,
tlm.TLM_EnableSelection,
tlm.TLM_DisableSelection,
tlm.TLM_RemoveLightmapUV,
installopencv.TLM_Install_OpenCV
]
def register():
for cls in classes:
register_class(cls)
def unregister():
for cls in classes:
unregister_class(cls)

View File

@ -0,0 +1,67 @@
import bpy, math, os, platform, subprocess, sys, re, shutil
def ShowMessageBox(message = "", title = "Message Box", icon = 'INFO'):
def draw(self, context):
self.layout.label(text=message)
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
class TLM_Install_OpenCV(bpy.types.Operator):
"""Install OpenCV"""
bl_idname = "tlm.install_opencv_lightmaps"
bl_label = "Install OpenCV"
bl_description = "Install OpenCV"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scene = context.scene
cycles = bpy.data.scenes[scene.name].cycles
print("Module OpenCV")
pythonbinpath = bpy.app.binary_path_python
if platform.system() == "Windows":
pythonlibpath = os.path.join(os.path.dirname(os.path.dirname(pythonbinpath)), "lib")
else:
pythonlibpath = os.path.join(os.path.dirname(os.path.dirname(pythonbinpath)), "lib", os.path.basename(pythonbinpath)[:-1])
ensurepippath = os.path.join(pythonlibpath, "ensurepip")
cmda = [pythonbinpath, ensurepippath, "--upgrade", "--user"]
pip = subprocess.run(cmda, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if pip.returncode == 0:
print("Sucessfully installed pip!\n")
else:
try:
import pip
module_pip = True
except ImportError:
#pip
module_pip = False
if not module_pip:
print("Failed to install pip!\n")
ShowMessageBox("Failed to install pip - Please start Blender as administrator", "Restart", 'PREFERENCES')
return{'FINISHED'}
cmdb = [pythonbinpath, "-m", "pip", "install", "opencv-python"]
opencv = subprocess.run(cmdb, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if opencv.returncode == 0:
print("Sucessfully installed OpenCV!\n")
else:
print("Failed to install OpenCV!\n")
ShowMessageBox("Failed to install opencv - Please start Blender as administrator", "Restart", 'PREFERENCES')
return{'FINISHED'}
module_opencv = True
print("Sucessfully installed OpenCV!\n")
ShowMessageBox("Please restart blender to enable OpenCV filtering", "Restart", 'PREFERENCES')
return{'FINISHED'}

View File

@ -0,0 +1,156 @@
import bpy, os, time, blf, webbrowser
from .. utility import build
from .. utility.cycles import cache
class TLM_BuildLightmaps(bpy.types.Operator):
bl_idname = "tlm.build_lightmaps"
bl_label = "Build Lightmaps"
bl_description = "Build Lightmaps"
bl_options = {'REGISTER', 'UNDO'}
def modal(self, context, event):
#Add progress bar from 0.15
print("MODAL")
return {'PASS_THROUGH'}
def invoke(self, context, event):
if not bpy.app.background:
build.prepare_build(self, False)
else:
print("Running in background mode. Contextual operator not available. Use command 'thelightmapper.addon.build.prepare_build()'")
return {'RUNNING_MODAL'}
def cancel(self, context):
pass
def draw_callback_px(self, context, event):
pass
class TLM_CleanLightmaps(bpy.types.Operator):
bl_idname = "tlm.clean_lightmaps"
bl_label = "Clean Lightmaps"
bl_description = "Clean Lightmaps"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scene = context.scene
filepath = bpy.data.filepath
dirpath = os.path.join(os.path.dirname(bpy.data.filepath), scene.TLM_EngineProperties.tlm_lightmap_savedir)
if os.path.isdir(dirpath):
for file in os.listdir(dirpath):
os.remove(os.path.join(dirpath + "/" + file))
for obj in bpy.data.objects:
if obj.type == "MESH":
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
cache.backup_material_restore(obj)
for obj in bpy.data.objects:
if obj.type == "MESH":
if obj.TLM_ObjectProperties.tlm_mesh_lightmap_use:
cache.backup_material_rename(obj)
for mat in bpy.data.materials:
if mat.users < 1:
bpy.data.materials.remove(mat)
for mat in bpy.data.materials:
if mat.name.startswith("."):
if "_Original" in mat.name:
bpy.data.materials.remove(mat)
for image in bpy.data.images:
if image.name.endswith("_baked"):
bpy.data.images.remove(image, do_unlink=True)
return {'FINISHED'}
class TLM_ExploreLightmaps(bpy.types.Operator):
bl_idname = "tlm.explore_lightmaps"
bl_label = "Explore Lightmaps"
bl_description = "Explore Lightmaps"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scene = context.scene
cycles = scene.cycles
if not bpy.data.is_saved:
self.report({'INFO'}, "Please save your file first")
return {"CANCELLED"}
filepath = bpy.data.filepath
dirpath = os.path.join(os.path.dirname(bpy.data.filepath), scene.TLM_EngineProperties.tlm_lightmap_savedir)
if os.path.isdir(dirpath):
webbrowser.open('file://' + dirpath)
else:
os.mkdir(dirpath)
webbrowser.open('file://' + dirpath)
return {'FINISHED'}
class TLM_EnableSelection(bpy.types.Operator):
"""Enable for selection"""
bl_idname = "tlm.enable_selection"
bl_label = "Enable for selection"
bl_description = "Enable for selection"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
scene = context.scene
for obj in bpy.context.selected_objects:
obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = True
if scene.TLM_SceneProperties.tlm_override_object_settings:
obj.TLM_ObjectProperties.tlm_mesh_lightmap_resolution = scene.TLM_SceneProperties.tlm_mesh_lightmap_resolution
obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_mode = scene.TLM_SceneProperties.tlm_mesh_lightmap_unwrap_mode
obj.TLM_ObjectProperties.tlm_mesh_lightmap_unwrap_margin = scene.TLM_SceneProperties.tlm_mesh_unwrap_margin
return{'FINISHED'}
class TLM_DisableSelection(bpy.types.Operator):
"""Disable for selection"""
bl_idname = "tlm.disable_selection"
bl_label = "Disable for selection"
bl_description = "Disable for selection"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
for obj in bpy.context.selected_objects:
obj.TLM_ObjectProperties.tlm_mesh_lightmap_use = False
return{'FINISHED'}
class TLM_RemoveLightmapUV(bpy.types.Operator):
"""Remove Lightmap UV for selection"""
bl_idname = "tlm.remove_uv_selection"
bl_label = "Remove Lightmap UV"
bl_description = "Remove Lightmap UV for selection"
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
for obj in bpy.context.selected_objects:
if obj.type == "MESH":
uv_layers = obj.data.uv_layers
for uvlayer in uv_layers:
if uvlayer.name == "UVMap_Lightmap":
uv_layers.remove(uvlayer)
return{'FINISHED'}

View File

@ -0,0 +1,16 @@
import bpy
from bpy.utils import register_class, unregister_class
from . import addon_preferences
#from . import build, clean, explore, encode, installopencv
classes = [
addon_preferences.TLM_AddonPreferences
]
def register():
for cls in classes:
register_class(cls)
def unregister():
for cls in classes:
unregister_class(cls)

View File

@ -0,0 +1,72 @@
import bpy
from os.path import basename, dirname
from bpy.types import AddonPreferences
from .. operators import installopencv
import importlib
class TLM_AddonPreferences(AddonPreferences):
bl_idname = "thelightmapper"
addon_keys = bpy.context.preferences.addons.keys()
def draw(self, context):
layout = self.layout
box = layout.box()
row = box.row()
row.label(text="OpenCV")
cv2 = importlib.util.find_spec("cv2")
if cv2 is not None:
row.label(text="OpenCV installed")
else:
row.label(text="OpenCV not found - Install as administrator!", icon_value=2)
row = box.row()
row.operator("tlm.install_opencv_lightmaps", icon="PREFERENCES")
box = layout.box()
row = box.row()
row.label(text="Blender Xatlas")
if "blender_xatlas" in self.addon_keys:
row.label(text="Blender Xatlas installed and available")
else:
row.label(text="Blender Xatlas not installed", icon_value=2)
row = box.row()
row.label(text="Github: https://github.com/mattedicksoncom/blender-xatlas")
box = layout.box()
row = box.row()
row.label(text="RizomUV Bridge")
row.label(text="Coming soon")
box = layout.box()
row = box.row()
row.label(text="UVPackmaster")
row.label(text="Coming soon")
box = layout.box()
row = box.row()
row.label(text="Texel Density Checker")
row.label(text="Coming soon")
box = layout.box()
row = box.row()
row.label(text="LuxCoreRender")
row.label(text="Coming soon")
box = layout.box()
row = box.row()
row.label(text="OctaneRender")
row.label(text="Coming soon")
# row = layout.row()
# row.label(text="PIP")
# row = layout.row()
# row.label(text="OIDN / Optix")
# row = layout.row()
# row.label(text="UVPackmaster")
# row = layout.row()
# row.label(text="Texel Density")

View File

@ -0,0 +1,33 @@
import bpy
from bpy.utils import register_class, unregister_class
from . import scene, object
from . renderer import cycles
from . denoiser import oidn, optix
classes = [
scene.TLM_SceneProperties,
object.TLM_ObjectProperties,
cycles.TLM_CyclesSceneProperties,
oidn.TLM_OIDNEngineProperties,
optix.TLM_OptixEngineProperties
]
def register():
for cls in classes:
register_class(cls)
bpy.types.Scene.TLM_SceneProperties = bpy.props.PointerProperty(type=scene.TLM_SceneProperties)
bpy.types.Object.TLM_ObjectProperties = bpy.props.PointerProperty(type=object.TLM_ObjectProperties)
bpy.types.Scene.TLM_EngineProperties = bpy.props.PointerProperty(type=cycles.TLM_CyclesSceneProperties)
bpy.types.Scene.TLM_OIDNEngineProperties = bpy.props.PointerProperty(type=oidn.TLM_OIDNEngineProperties)
bpy.types.Scene.TLM_OptixEngineProperties = bpy.props.PointerProperty(type=optix.TLM_OptixEngineProperties)
def unregister():
for cls in classes:
unregister_class(cls)
del bpy.types.Scene.TLM_SceneProperties
del bpy.types.Object.TLM_ObjectProperties
del bpy.types.Scene.TLM_EngineProperties
del bpy.types.Scene.TLM_OIDNEngineProperties
del bpy.types.Scene.TLM_OptixEngineProperties

View File

@ -0,0 +1,4 @@
import bpy
from bpy.props import *
class TLM_IntegratedDenoiseEngineProperties(bpy.types.PropertyGroup):

View File

@ -0,0 +1,39 @@
import bpy
from bpy.props import *
class TLM_OIDNEngineProperties(bpy.types.PropertyGroup):
tlm_oidn_path : StringProperty(
name="OIDN Path",
description="The path to the OIDN binaries",
default="",
subtype="FILE_PATH")
tlm_oidn_verbose : BoolProperty(
name="Verbose",
description="TODO")
tlm_oidn_threads : IntProperty(
name="Threads",
default=0,
min=0,
max=64,
description="Amount of threads to use. Set to 0 for auto-detect.")
tlm_oidn_maxmem : IntProperty(
name="Tiling max Memory",
default=0,
min=512,
max=32768,
description="Use tiling for memory conservation. Set to 0 to disable tiling.")
tlm_oidn_affinity : BoolProperty(
name="Set Affinity",
description="TODO")
tlm_oidn_use_albedo : BoolProperty(
name="Use albedo map",
description="TODO")
tlm_oidn_use_normal : BoolProperty(
name="Use normal map",
description="TODO")

View File

@ -0,0 +1,21 @@
import bpy
from bpy.props import *
class TLM_OptixEngineProperties(bpy.types.PropertyGroup):
tlm_optix_path : StringProperty(
name="Optix Path",
description="TODO",
default="",
subtype="FILE_PATH")
tlm_optix_verbose : BoolProperty(
name="Verbose",
description="TODO")
tlm_optix_maxmem : IntProperty(
name="Tiling max Memory",
default=0,
min=512,
max=32768,
description="Use tiling for memory conservation. Set to 0 to disable tiling.")

View File

@ -0,0 +1,4 @@
import bpy
from bpy.props import *
class TLM_FilteringProperties(bpy.types.PropertyGroup):

View File

@ -0,0 +1,121 @@
import bpy
from bpy.props import *
class TLM_ObjectProperties(bpy.types.PropertyGroup):
addon_keys = bpy.context.preferences.addons.keys()
tlm_atlas_pointer : StringProperty(
name = "Atlas Group",
description = "Atlas Lightmap Group",
default = "")
tlm_mesh_lightmap_use : BoolProperty(
name="Enable Lightmapping",
description="TODO",
default=False)
tlm_mesh_lightmap_resolution : EnumProperty(
items = [('32', '32', 'TODO'),
('64', '64', 'TODO'),
('128', '128', 'TODO'),
('256', '256', 'TODO'),
('512', '512', 'TODO'),
('1024', '1024', 'TODO'),
('2048', '2048', 'TODO'),
('4096', '4096', 'TODO'),
('8192', '8192', 'TODO')],
name = "Lightmap Resolution",
description="TODO",
default='256')
unwrap_modes = [('Lightmap', 'Lightmap', 'TODO'),('SmartProject', 'Smart Project', 'TODO'),('CopyExisting', 'Copy Existing', 'TODO'),('AtlasGroup', 'Atlas Group', 'TODO')]
if "blender_xatlas" in addon_keys:
unwrap_modes.append(('Xatlas', 'Xatlas', 'TODO'))
tlm_mesh_lightmap_unwrap_mode : EnumProperty(
items = unwrap_modes,
name = "Unwrap Mode",
description="TODO",
default='SmartProject')
tlm_mesh_unwrap_margin : FloatProperty(
name="Unwrap Margin",
default=0.1,
min=0.0,
max=1.0,
subtype='FACTOR')
tlm_mesh_filter_override : BoolProperty(
name="Override filtering",
description="Override the scene specific filtering",
default=False)
#FILTERING SETTINGS GROUP
tlm_mesh_filtering_engine : EnumProperty(
items = [('OpenCV', 'OpenCV', 'Make use of OpenCV based image filtering (Requires it to be installed first in the preferences panel)'),
('Numpy', 'Numpy', 'Make use of Numpy based image filtering (Integrated)')],
name = "Filtering library",
description="Select which filtering library to use.",
default='Numpy')
#Numpy Filtering options
tlm_mesh_numpy_filtering_mode : EnumProperty(
items = [('Blur', 'Blur', 'Basic blur filtering.')],
name = "Filter",
description="TODO",
default='Blur')
#OpenCV Filtering options
tlm_mesh_filtering_mode : EnumProperty(
items = [('Box', 'Box', 'Basic box blur'),
('Gaussian', 'Gaussian', 'Gaussian blurring'),
('Bilateral', 'Bilateral', 'Edge-aware filtering'),
('Median', 'Median', 'Median blur')],
name = "Filter",
description="TODO",
default='Median')
tlm_mesh_filtering_gaussian_strength : IntProperty(
name="Gaussian Strength",
default=3,
min=1,
max=50)
tlm_mesh_filtering_iterations : IntProperty(
name="Filter Iterations",
default=5,
min=1,
max=50)
tlm_mesh_filtering_box_strength : IntProperty(
name="Box Strength",
default=1,
min=1,
max=50)
tlm_mesh_filtering_bilateral_diameter : IntProperty(
name="Pixel diameter",
default=3,
min=1,
max=50)
tlm_mesh_filtering_bilateral_color_deviation : IntProperty(
name="Color deviation",
default=75,
min=1,
max=100)
tlm_mesh_filtering_bilateral_coordinate_deviation : IntProperty(
name="Color deviation",
default=75,
min=1,
max=100)
tlm_mesh_filtering_median_kernel : IntProperty(
name="Median kernel",
default=3,
min=1,
max=5)

View File

@ -0,0 +1,87 @@
import bpy
from bpy.props import *
class TLM_CyclesSceneProperties(bpy.types.PropertyGroup):
tlm_mode : EnumProperty(
items = [('CPU', 'CPU', 'Use the processor to bake textures'),
('GPU', 'GPU', 'Use the graphics card to bake textures')],
name = "Device",
description="Select whether to use the CPU or the GPU for baking",
default="CPU")
tlm_quality : EnumProperty(
items = [('0', 'Exterior Preview', 'Best for fast exterior previz'),
('1', 'Interior Preview', 'Best for fast interior previz with bounces'),
('2', 'Medium', 'Best for complicated interior preview and final for isometric environments'),
('3', 'High', 'Best used for final baking for 3rd person games'),
('4', 'Production', 'Best for first-person and Archviz'),
('5', 'Custom', 'Uses the cycles sample settings provided the user')],
name = "Quality",
description="Select baking quality",
default="0")
tlm_resolution_scale : EnumProperty(
items = [('1', '1/1', '1'),
('2', '1/2', '2'),
('4', '1/4', '4'),
('8', '1/8', '8')],
name = "Resolution scale",
description="Select resolution scale",
default="2")
tlm_setting_supersample : EnumProperty(
items = [('none', 'None', 'No supersampling'),
('2x', '2x', 'Double supersampling'),
('4x', '4x', 'Quadruple supersampling')],
name = "Supersampling",
description="Supersampling scale",
default="none")
tlm_bake_mode : EnumProperty(
items = [('Background', 'Background', 'More overhead; allows for network.'),
('Foreground', 'Foreground', 'Direct in-session bake')],
name = "Baking mode",
description="Select bake mode",
default="Foreground")
tlm_caching_mode : EnumProperty(
items = [('Copy', 'Copy', 'More overhead; allows for network.'),
('Cache', 'Cache', 'Cache in separate blend'),
('Node', 'Node restore', 'EXPERIMENTAL! Use with care')],
name = "Caching mode",
description="Select cache mode",
default="Copy")
tlm_directional_mode : EnumProperty(
items = [('None', 'None', 'No directional information'),
('Normal', 'Baked normal', 'Baked normal maps are taken into consideration')],
name = "Directional mode",
description="Select directional mode",
default="None")
tlm_lightmap_savedir : StringProperty(
name="Lightmap Directory",
description="TODO",
default="Lightmaps",
subtype="FILE_PATH")
tlm_dilation_margin : IntProperty(
name="Dilation margin",
default=4,
min=1,
max=64,
subtype='PIXEL')
tlm_exposure_multiplier : FloatProperty(
name="Exposure Multiplier",
default=0,
description="0 to disable. Multiplies GI value")
tlm_metallic_handling_mode : EnumProperty(
items = [('ignore', 'Ignore', 'No directional information'),
('clamp', 'Clamp', 'Clamp to value 0.9'),
('zero', 'Zero', 'Temporarily set to 0 during baking, and reapply after')],
name = "Metallic handling",
description="Set metallic handling mode to prevent black-baking.",
default="ignore")

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