mirror of
https://github.com/antopilo/Nuake.git
synced 2025-12-30 21:49:06 +03:00
Compare commits
2 Commits
30b5ccc339
...
6d7a3a09b1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d7a3a09b1 | ||
|
|
67916d0307 |
@@ -13,8 +13,8 @@ struct Vertex
|
||||
float uv_x;
|
||||
float3 normal;
|
||||
float uv_y;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
float4 tangent;
|
||||
float4 bitangent;
|
||||
};
|
||||
|
||||
[[vk::binding(0, 1)]]
|
||||
@@ -86,7 +86,8 @@ struct PSInput
|
||||
float3 Color : TEXCOORD0;
|
||||
float2 UV : TEXCOORD1;
|
||||
float3 Normal : TEXCOORD2;
|
||||
//float3x3 TBN : TEXCOORD3;
|
||||
float3 Tangent : TEXCOORD3;
|
||||
float3 Bitangent : TEXCOORD4;
|
||||
};
|
||||
|
||||
struct PSOutput {
|
||||
@@ -107,6 +108,8 @@ struct ModelPushConstant
|
||||
[[vk::push_constant]]
|
||||
ModelPushConstant pushConstants;
|
||||
|
||||
|
||||
|
||||
PSOutput main(PSInput input)
|
||||
{
|
||||
PSOutput output;
|
||||
@@ -114,13 +117,26 @@ PSOutput main(PSInput input)
|
||||
Material inMaterial = material[pushConstants.materialIndex];
|
||||
// NORMAL
|
||||
// TODO use TBN matrix
|
||||
float3 normal = float3(0.5, 0.5, 1.0);
|
||||
float3 T = input.Tangent.xyz;
|
||||
float3 B = input.Bitangent.xyz;
|
||||
float3 N = input.Normal.xyz;
|
||||
float3x3 TBN = float3x3(T, B, N);
|
||||
|
||||
float3 normal = float3(0.0, 0.0, 1.0);
|
||||
if(inMaterial.hasNormal == 1)
|
||||
{
|
||||
// Sample from texture.
|
||||
normal = textures[inMaterial.normalTextureId].Sample(mySampler, input.UV).rgb;
|
||||
normal.xyz = normal.zxy;
|
||||
normal = normal * 2.0f - 1.0f;
|
||||
}
|
||||
//normal = mul(input.TBN, normal);
|
||||
normal = input.Normal / 2.0f + 0.5f;
|
||||
else
|
||||
{
|
||||
normal = normal;
|
||||
}
|
||||
|
||||
//normal = input.Normal;
|
||||
normal = mul(transpose(TBN), normal);
|
||||
normal = normal / 2.0f + 0.5f;
|
||||
output.oNormal = float4(normal, 1.0f);
|
||||
|
||||
// MATERIAL
|
||||
|
||||
@@ -13,8 +13,8 @@ struct Vertex
|
||||
float uv_x;
|
||||
float3 normal;
|
||||
float uv_y;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
float4 tangent;
|
||||
float4 bitangent;
|
||||
};
|
||||
|
||||
[[vk::binding(0, 1)]]
|
||||
@@ -98,9 +98,35 @@ struct VSOutput
|
||||
float3 Color : TEXCOORD0;
|
||||
float2 UV : TEXCOORD1;
|
||||
float3 Normal : TEXCOORD2;
|
||||
//float3x3 TBN : TEXCOORD3;
|
||||
float3 Tangent : TEXCOORD3;
|
||||
float3 Bitangent : TEXCOORD4;
|
||||
};
|
||||
|
||||
float3x3 invert(float3x3 m)
|
||||
{
|
||||
float3 a = m[0];
|
||||
float3 b = m[1];
|
||||
float3 c = m[2];
|
||||
|
||||
float3 r0 = cross(b, c);
|
||||
float3 r1 = cross(c, a);
|
||||
float3 r2 = cross(a, b);
|
||||
|
||||
float det = dot(r2, c);
|
||||
|
||||
// Return identity if not invertible (optional fallback)
|
||||
if (abs(det) < 1e-6)
|
||||
return float3x3(1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0);
|
||||
|
||||
float invDet = 1.0 / det;
|
||||
|
||||
return float3x3(r0 * invDet,
|
||||
r1 * invDet,
|
||||
r2 * invDet);
|
||||
}
|
||||
|
||||
// Main vertex shader
|
||||
VSOutput main(uint vertexIndex : SV_VertexID)
|
||||
{
|
||||
@@ -116,11 +142,13 @@ VSOutput main(uint vertexIndex : SV_VertexID)
|
||||
output.Position = mul(camView.Projection, mul(camView.View, mul(modelData.model, float4(v.position, 1.0f))));
|
||||
output.Color = normalize(float3(v.position.xyz));
|
||||
output.UV = float2(v.uv_x, v.uv_y);
|
||||
output.Normal = normalize(v.normal);
|
||||
|
||||
float3x3 upper3x3 = (float3x3)modelData.model;
|
||||
float3x3 normalMatrix = transpose(invert(upper3x3));
|
||||
output.Bitangent = mul(normalMatrix, normalize(v.bitangent.xyz));
|
||||
output.Normal = mul(normalMatrix, normalize(v.normal.xyz));
|
||||
output.Tangent = mul(normalMatrix, normalize(v.tangent.xyz));
|
||||
|
||||
//float3 T = normalize(mul((float3x3)modelData.model, normalize(v.tangent.xyz)));
|
||||
//float3 B = normalize(mul((float3x3)modelData.model, normalize(v.bitangent.xyz)));
|
||||
//float3 N = normalize(mul((float3x3)modelData.model, normalize(v.normal)).xyz);
|
||||
//output.TBN = transpose(float3x3(T, B, N));
|
||||
//output.Normal = v.normal.xyz;
|
||||
return output;
|
||||
}
|
||||
@@ -227,7 +227,7 @@ int GetCSMSplit(float depth)
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
PSOutput main(PSInput input)
|
||||
@@ -253,7 +253,7 @@ PSOutput main(PSInput input)
|
||||
if(rayLength > 1000.0)
|
||||
{
|
||||
output.oColor0 = float4(0.0f, 0.0f, 0, 0.0f);
|
||||
return output;
|
||||
//return output;
|
||||
}
|
||||
|
||||
float stepLength = rayLength / pushConstants.StepCount;
|
||||
@@ -272,24 +272,33 @@ PSOutput main(PSInput input)
|
||||
float lightDepth = length(worldPos - camView.Position);
|
||||
int splitIndex = GetCSMSplit(lightDepth);
|
||||
|
||||
CameraView lightView = cameras[light.transformId[splitIndex]];
|
||||
float4 fragPosLightSpace = mul(lightView.Projection, mul(lightView.View, float4(currentPosition, 1.0)));
|
||||
float3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
projCoords.xy = projCoords.xy * 0.5 + 0.5;
|
||||
|
||||
float currentDepth = projCoords.z;
|
||||
float closestDepth = textures[light.shadowMapTextureId[splitIndex]].Sample(mySampler, projCoords.xy).r;
|
||||
|
||||
float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time);
|
||||
float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale;
|
||||
if(closestDepth < currentDepth)
|
||||
if(splitIndex == -1)
|
||||
{
|
||||
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Exponant * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0);
|
||||
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Exponant;
|
||||
}
|
||||
else
|
||||
{
|
||||
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Ambient * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0);
|
||||
CameraView lightView = cameras[light.transformId[splitIndex]];
|
||||
float4 fragPosLightSpace = mul(lightView.Projection, mul(lightView.View, float4(currentPosition, 1.0)));
|
||||
float3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
projCoords.xy = projCoords.xy * 0.5 + 0.5;
|
||||
|
||||
float currentDepth = projCoords.z;
|
||||
float closestDepth = textures[light.shadowMapTextureId[splitIndex]].Sample(mySampler, projCoords.xy).r;
|
||||
|
||||
float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time);
|
||||
float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale;
|
||||
if(closestDepth < currentDepth)
|
||||
{
|
||||
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Exponant * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Ambient * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if(light.type == 1)
|
||||
{
|
||||
|
||||
@@ -1,141 +1,321 @@
|
||||
#shader vertex
|
||||
#version 440 core
|
||||
|
||||
layout(location = 0) in vec3 VertexPosition;
|
||||
layout(location = 1) in vec2 UVPosition;
|
||||
|
||||
out flat vec2 UV;
|
||||
out mat4 InvView;
|
||||
out mat4 InvProjection;
|
||||
|
||||
uniform mat4 u_View;
|
||||
uniform mat4 u_Projection;
|
||||
|
||||
void main()
|
||||
// Transforms
|
||||
struct ModelData
|
||||
{
|
||||
UV = UVPosition;
|
||||
InvView = inverse(u_View);
|
||||
InvProjection = inverse(u_Projection);
|
||||
gl_Position = vec4(VertexPosition, 1.0f);
|
||||
}
|
||||
float4x4 model;
|
||||
};
|
||||
[[vk::binding(0, 0)]]
|
||||
StructuredBuffer<ModelData> model : register(t1);
|
||||
|
||||
#shader fragment
|
||||
#version 440 core
|
||||
|
||||
float ditherPattern[4][4] = { { 0.0f, 0.5f, 0.125f, 0.625f},
|
||||
{ 0.75f, 0.22f, 0.875f, 0.375f},
|
||||
{ 0.1875f, 0.6875f, 0.0625f, 0.5625},
|
||||
{ 0.9375f, 0.4375f, 0.8125f, 0.3125} };
|
||||
|
||||
in mat4 InvView;
|
||||
in mat4 InvProjection;
|
||||
|
||||
uniform sampler2D u_Depth;
|
||||
|
||||
uniform vec3 u_CamPosition;
|
||||
uniform int u_StepCount;
|
||||
uniform float u_FogAmount;
|
||||
uniform float u_Exponant;
|
||||
|
||||
const int MAX_LIGHT = 20;
|
||||
uniform int u_LightCount;
|
||||
|
||||
struct Light {
|
||||
mat4 transform;
|
||||
vec3 color;
|
||||
vec3 direction;
|
||||
sampler2D shadowmap;
|
||||
float strength;
|
||||
// Vertex
|
||||
struct Vertex
|
||||
{
|
||||
float3 position;
|
||||
float uv_x;
|
||||
float3 normal;
|
||||
float uv_y;
|
||||
float3 tangent;
|
||||
float3 bitangent;
|
||||
};
|
||||
|
||||
uniform Light u_Lights[MAX_LIGHT];
|
||||
[[vk::binding(0, 1)]]
|
||||
StructuredBuffer<Vertex> vertexBuffer : register(t2);
|
||||
|
||||
uniform sampler2D lightShadowmap;
|
||||
in vec2 UV;
|
||||
// Samplers
|
||||
[[vk::binding(0, 2)]]
|
||||
SamplerState mySampler : register(s0);
|
||||
|
||||
out vec4 FragColor;
|
||||
const float PI = 3.141592653589793f;
|
||||
// Materials
|
||||
struct Material
|
||||
{
|
||||
bool hasAlbedo;
|
||||
float3 albedo;
|
||||
bool hasNormal;
|
||||
bool hasMetalness;
|
||||
bool hasRoughness;
|
||||
bool hasAO;
|
||||
float metalnessValue;
|
||||
float roughnessValue;
|
||||
float aoValue;
|
||||
int albedoTextureId;
|
||||
int normalTextureId;
|
||||
int metalnessTextureId;
|
||||
int roughnessTextureId;
|
||||
int aoTextureId;
|
||||
};
|
||||
[[vk::binding(0, 3)]]
|
||||
StructuredBuffer<Material> material;
|
||||
|
||||
// Textures
|
||||
[[vk::binding(0, 4)]]
|
||||
Texture2D textures[];
|
||||
|
||||
// Lights
|
||||
struct Light
|
||||
{
|
||||
float3 position;
|
||||
int type;
|
||||
float4 color;
|
||||
float3 direction;
|
||||
float outerConeAngle;
|
||||
float innerConeAngle;
|
||||
bool castShadow;
|
||||
int shadowMapTextureId[4];
|
||||
int transformId[4];
|
||||
};
|
||||
|
||||
[[vk::binding(0, 5)]]
|
||||
StructuredBuffer<Light> lights;
|
||||
|
||||
// Cameras
|
||||
struct CameraView {
|
||||
float4x4 View;
|
||||
float4x4 Projection;
|
||||
float4x4 ViewProjection;
|
||||
float4x4 InverseView;
|
||||
float4x4 InverseProjection;
|
||||
float3 Position;
|
||||
float Near;
|
||||
float Far;
|
||||
};
|
||||
[[vk::binding(0, 6)]]
|
||||
StructuredBuffer<CameraView> cameras;
|
||||
|
||||
struct PSInput
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float2 UV : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct PSOutput {
|
||||
float4 oColor0 : SV_TARGET;
|
||||
};
|
||||
|
||||
struct VolumetricConstant
|
||||
{
|
||||
int DepthTextureID;
|
||||
int StepCount;
|
||||
float FogAmount;
|
||||
float Exponant;
|
||||
int CamViewID;
|
||||
int LightCount;
|
||||
float Ambient;
|
||||
float Time;
|
||||
float NoiseSpeed;
|
||||
float NoiseScale;
|
||||
float NoiseStrength;
|
||||
};
|
||||
|
||||
[[vk::push_constant]]
|
||||
VolumetricConstant pushConstants;
|
||||
|
||||
float2 GetTexelSize(Texture2D tex)
|
||||
{
|
||||
uint width, height;
|
||||
tex.GetDimensions(width, height);
|
||||
return 1.0 / float2(width, height);
|
||||
}
|
||||
|
||||
float LinearizeDepth(float depth, float nearPlane, float farPlane)
|
||||
{
|
||||
return (2.0 * nearPlane) / (farPlane + nearPlane - (1.0 - depth) * (farPlane - nearPlane));
|
||||
}
|
||||
|
||||
// Mie scaterring approximated with Henyey-Greenstein phase function.
|
||||
float ComputeScattering(float lightDotView)
|
||||
{
|
||||
float result = 1.0f - u_FogAmount ;
|
||||
result /= (4.0f * PI * pow(1.0f + u_FogAmount * u_FogAmount - (1.0f * u_FogAmount) * lightDotView, 1.5f));
|
||||
float PI = 3.141592653589793f;
|
||||
float result = 1.0f - pushConstants.FogAmount;
|
||||
result /= (4.0f * PI * pow(1.0f + pushConstants.FogAmount * pushConstants.FogAmount - (1.0f * pushConstants.FogAmount) * lightDotView, 1.5f));
|
||||
return result;
|
||||
}
|
||||
|
||||
vec3 ComputeVolumetric(vec3 FragPos, Light light)
|
||||
float3 WorldPosFromDepth(float depth, float2 uv, float4x4 invProj, float4x4 invView)
|
||||
{
|
||||
vec3 startPosition = u_CamPosition; // Camera Position
|
||||
vec3 rayVector = FragPos - startPosition; // Ray Direction
|
||||
|
||||
float rayLength = length(rayVector); // Length of the raymarched
|
||||
if(rayLength > 1000.0)
|
||||
return vec3(0.0);
|
||||
float stepLength = rayLength / u_StepCount; // Step length
|
||||
vec3 rayDirection = rayVector / rayLength;
|
||||
vec3 step = rayDirection * stepLength; // Normalized to step length direction
|
||||
|
||||
vec3 accumFog = vec3(0.0f, 0.0f, 0.0f); // accumulative color
|
||||
|
||||
// Raymarching
|
||||
vec3 currentPosition = startPosition;
|
||||
for (int i = 0; i < u_StepCount; i++)
|
||||
{
|
||||
vec4 fragPosLightSpace = light.transform * vec4(currentPosition, 1.0f);
|
||||
// perform perspective divide
|
||||
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
|
||||
// transform to [0,1] range
|
||||
projCoords = projCoords * 0.5 + 0.5;
|
||||
|
||||
float currentDepth = projCoords.z;
|
||||
float closestDepth = texture(light.shadowmap, projCoords.xy).r;
|
||||
if (closestDepth > currentDepth && closestDepth < 999)
|
||||
{
|
||||
//accumFog = vec3(light.color);
|
||||
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).xxx * light.color);
|
||||
//accumFog = vec3(projCoords.x, projCoords.y, 1.0);
|
||||
|
||||
}
|
||||
currentPosition += step * ditherPattern[int(gl_FragCoord.x) % 4][int(gl_FragCoord.y) % 4];
|
||||
//accumFog = vec3(projCoords);
|
||||
}
|
||||
accumFog /= u_StepCount;
|
||||
|
||||
return accumFog;
|
||||
}
|
||||
|
||||
// Converts depth to World space coords.
|
||||
vec3 WorldPosFromDepth(float depth) {
|
||||
float z = depth * 2.0 - 1.0;
|
||||
|
||||
vec4 clipSpacePosition = vec4(UV * 2.0 - 1.0, z, 1.0);
|
||||
vec4 viewSpacePosition = InvProjection * clipSpacePosition;
|
||||
|
||||
// Perspective division
|
||||
float z = depth;
|
||||
float4 clipSpacePosition = float4(uv.x * 2.0 - 1.0, (uv.y * 2.0 - 1.0), z, 1.0f);
|
||||
float4 viewSpacePosition = mul(invProj, clipSpacePosition);
|
||||
viewSpacePosition /= viewSpacePosition.w;
|
||||
|
||||
vec4 worldSpacePosition = InvView * viewSpacePosition;
|
||||
|
||||
float4 worldSpacePosition = mul(invView, viewSpacePosition);
|
||||
return worldSpacePosition.xyz;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float depth = texture(u_Depth, UV).r;
|
||||
vec3 globalFragmentPosition = WorldPosFromDepth(depth);
|
||||
// Simplex 3D Noise
|
||||
float mod289(float x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
||||
float3 mod289(float3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
||||
float4 mod289(float4 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
||||
|
||||
vec3 fog = vec3(0, 0, 0);
|
||||
for (int i = 0; i < u_LightCount; i++)
|
||||
float4 permute(float4 x) { return mod289(((x*34.0)+1.0)*x); }
|
||||
|
||||
float4 taylorInvSqrt(float4 r) { return 1.79284291400159 - 0.85373472095314 * r; }
|
||||
|
||||
float snoise(float3 v)
|
||||
{
|
||||
const float2 C = float2(1.0/6.0, 1.0/3.0) ;
|
||||
const float4 D = float4(0.0, 0.5, 1.0, 2.0);
|
||||
|
||||
// First corner
|
||||
float3 i = floor(v + dot(v, C.yyy));
|
||||
float3 x0 = v - i + dot(i, C.xxx);
|
||||
|
||||
// Other corners
|
||||
float3 g = step(x0.yzx, x0.xyz);
|
||||
float3 l = 1.0 - g;
|
||||
float3 i1 = min(g.xyz, l.zxy);
|
||||
float3 i2 = max(g.xyz, l.zxy);
|
||||
|
||||
// x0 = x0 - 0.0 + 0.0 * C.xxx;
|
||||
float3 x1 = x0 - i1 + C.xxx;
|
||||
float3 x2 = x0 - i2 + C.yyy;
|
||||
float3 x3 = x0 - 1.0 + 3.0 * C.xxx;
|
||||
|
||||
// Permutations
|
||||
i = mod289(i);
|
||||
float4 p = permute(permute(permute(
|
||||
i.z + float4(0.0, i1.z, i2.z, 1.0))
|
||||
+ i.y + float4(0.0, i1.y, i2.y, 1.0))
|
||||
+ i.x + float4(0.0, i1.x, i2.x, 1.0));
|
||||
|
||||
// Gradients: 7x7 points over a cube, mapped onto a unit sphere
|
||||
float4 j = p - 49.0 * floor(p * (1.0 / 49.0)); // mod(p,7*7)
|
||||
|
||||
float4 x_ = floor(j * (1.0 / 7.0));
|
||||
float4 y_ = floor(j - 7.0 * x_); // mod(j,7)
|
||||
|
||||
float4 x = (x_ * 2.0 + 0.5) / 7.0 - 1.0;
|
||||
float4 y = (y_ * 2.0 + 0.5) / 7.0 - 1.0;
|
||||
|
||||
float4 h = 1.0 - abs(x) - abs(y);
|
||||
|
||||
float4 b0 = float4(x.xy, y.xy);
|
||||
float4 b1 = float4(x.zw, y.zw);
|
||||
|
||||
float4 s0 = floor(b0) * 2.0 + 1.0;
|
||||
float4 s1 = floor(b1) * 2.0 + 1.0;
|
||||
float4 sh = -step(h, 0.0);
|
||||
|
||||
float4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
|
||||
float4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
|
||||
|
||||
float3 g0 = float3(a0.xy, h.x);
|
||||
float3 g1 = float3(a0.zw, h.y);
|
||||
float3 g2 = float3(a1.xy, h.z);
|
||||
float3 g3 = float3(a1.zw, h.w);
|
||||
|
||||
// Normalize gradients
|
||||
float4 norm = taylorInvSqrt(float4(dot(g0,g0), dot(g1,g1), dot(g2,g2), dot(g3,g3)));
|
||||
g0 *= norm.x;
|
||||
g1 *= norm.y;
|
||||
g2 *= norm.z;
|
||||
g3 *= norm.w;
|
||||
|
||||
// Mix final noise value
|
||||
float4 m = max(0.6 - float4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
|
||||
m = m * m;
|
||||
return 42.0 * dot(m*m, float4(dot(g0,x0), dot(g1,x1), dot(g2,x2), dot(g3,x3)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
PSOutput main(PSInput input)
|
||||
{
|
||||
float ditherPattern[4][4] = { { 0.0f, 0.5f, 0.125f, 0.625f},
|
||||
{ 0.75f, 0.22f, 0.875f, 0.375f},
|
||||
{ 0.1875f, 0.6875f, 0.0625f, 0.5625},
|
||||
{ 0.9375f, 0.4375f, 0.8125f, 0.3125} };
|
||||
|
||||
CameraView camView = cameras[pushConstants.CamViewID];
|
||||
float3 startPosition = camView.Position;
|
||||
|
||||
int depthTexture = pushConstants.DepthTextureID;
|
||||
float depth = textures[depthTexture].Sample(mySampler, input.UV).r;
|
||||
|
||||
float3 worldPos = WorldPosFromDepth(depth, input.UV, camView.InverseProjection, camView.InverseView);
|
||||
|
||||
float3 rayVector = worldPos - startPosition;
|
||||
|
||||
float rayLength = length(rayVector);
|
||||
|
||||
PSOutput output;
|
||||
if(rayLength > 1000.0)
|
||||
{
|
||||
fog += ComputeVolumetric(globalFragmentPosition, u_Lights[i]) * u_Exponant;
|
||||
output.oColor0 = float4(0.0f, 0.0f, 0, 0.0f);
|
||||
return output;
|
||||
}
|
||||
|
||||
FragColor = vec4(fog, 1.0);
|
||||
//FragColor = vec4(mix(fog, ComputeVolumetric(globalFragmentPosition, u_Lights[0]), 0.9f), 0.01);
|
||||
//FragColor = vec4(globalFragmentPosition * 10.0, 1.0f);
|
||||
//FragColor = vec4(globalFragmentPosition.xyz * 100.0, 1.0f);
|
||||
//FragColor = vec4(worldSpacePosition.x, worldSpacePosition.y, worldSpacePosition.z, 1);
|
||||
//FragColor = vec4(ComputeVolumetric(globalFragmentPosition, u_Lights[0]), 1.0);
|
||||
float stepLength = rayLength / pushConstants.StepCount;
|
||||
float3 rayDirection = rayVector / rayLength;
|
||||
float3 step = rayDirection * stepLength;
|
||||
|
||||
float3 accumFog = float3(0, 0, 0);
|
||||
float3 currentPosition = startPosition;
|
||||
for(int i = 0; i < pushConstants.StepCount; i++)
|
||||
{
|
||||
for(int l = 0; l < pushConstants.LightCount; l++)
|
||||
{
|
||||
Light light = lights[l];
|
||||
if(light.type == 0)
|
||||
{
|
||||
CameraView lightView = cameras[light.transformId[0]];
|
||||
float4 fragPosLightSpace = mul(lightView.Projection, mul(lightView.View, float4(currentPosition, 1.0)));
|
||||
float3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
|
||||
projCoords.xy = projCoords.xy * 0.5 + 0.5;
|
||||
|
||||
float currentDepth = projCoords.z;
|
||||
float closestDepth = textures[light.shadowMapTextureId[0]].Sample(mySampler, projCoords.xy).r;
|
||||
|
||||
float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time);
|
||||
float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale;
|
||||
if(closestDepth < currentDepth)
|
||||
{
|
||||
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Exponant * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
accumFog += (ComputeScattering(dot(rayDirection, light.direction)).rrr * light.color.xyz) * pushConstants.Ambient * ((snoise(noiseSamplePos.xyz) + 1.0) / 2.0);
|
||||
}
|
||||
}
|
||||
else if(light.type == 1)
|
||||
{
|
||||
float3 lightToFrag = currentPosition - light.position;
|
||||
float distance = length(lightToFrag);
|
||||
float3 lightDir = normalize(-lightToFrag);
|
||||
float attenuation = 1.0 / (distance * distance);
|
||||
attenuation = 1.0 - smoothstep(0.0, 3.0f, distance);
|
||||
float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time);
|
||||
float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale;
|
||||
float lightScatter = (snoise(noiseSamplePos.xyz) + 1.0) * 0.5;
|
||||
|
||||
float3 scatterTerm = ComputeScattering(dot(rayDirection, lightDir)).rrr * light.color.xyz;
|
||||
|
||||
accumFog += scatterTerm * lightScatter * pushConstants.Exponant * attenuation;
|
||||
}
|
||||
else if(light.type == 2)
|
||||
{
|
||||
float3 lightToFrag = currentPosition - light.position;
|
||||
float distance = length(lightToFrag);
|
||||
float3 lightDir = normalize(-lightToFrag);
|
||||
float attenuation = 1.0 / (distance * distance);
|
||||
attenuation = 1.0 - smoothstep(0.0, 6.0f, distance);
|
||||
float3 noiseOffset = float3(pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time, pushConstants.NoiseSpeed * pushConstants.Time);
|
||||
float3 noiseSamplePos = (currentPosition + noiseOffset) * pushConstants.NoiseScale;
|
||||
float lightScatter = (snoise(noiseSamplePos.xyz) + 1.0) * 0.5;
|
||||
|
||||
float theta = dot(lightDir, normalize(-light.direction));
|
||||
float epsilon = light.innerConeAngle - light.outerConeAngle;
|
||||
float intensity = clamp((theta - light.outerConeAngle) / epsilon, 0.0, 1.0);
|
||||
float3 scatterTerm = ComputeScattering(dot(rayDirection, lightDir)).rrr * light.color.xyz;
|
||||
accumFog += scatterTerm * lightScatter * pushConstants.Exponant * attenuation * intensity;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
currentPosition += step ;
|
||||
|
||||
}
|
||||
|
||||
accumFog /= pushConstants.StepCount;
|
||||
|
||||
output.oColor0 = float4(accumFog.x, accumFog.y, accumFog.z, 1.0f);
|
||||
return output;
|
||||
}
|
||||
@@ -6,12 +6,268 @@
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_internal.h>
|
||||
#include <Nuake/Scene/Components/CameraComponent.h>
|
||||
#include "Nuake/Rendering/Vulkan/SceneViewport.h"
|
||||
#include "Nuake/Scene/Entities/Entity.h"
|
||||
#include <Nuake/Scene/Components/ModelComponent.h>
|
||||
#include <Engine.h>
|
||||
#include "Nuake/Rendering/Vulkan/DebugCmd.h"
|
||||
#include "Nuake/Resource/Project.h"
|
||||
#include <Nuake/UI/ImUI.h>
|
||||
|
||||
Ref<Nuake::Model> sphereModel;
|
||||
Ref<Nuake::Model> quadModel;
|
||||
Ref<Nuake::Model> cubeModel;
|
||||
|
||||
enum class Shapes
|
||||
{
|
||||
Sphere, Cube, Quad
|
||||
};
|
||||
|
||||
Shapes currentShape = Shapes::Sphere;
|
||||
|
||||
MaterialEditor::MaterialEditor()
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
PreviewScene = CreateRef<Nuake::Scene>();
|
||||
PreviewScene->GetEnvironment()->mVolumetric->SetFogAmount(1.0f);
|
||||
|
||||
auto camera = PreviewScene->CreateEntity("Camera");
|
||||
camera.GetComponent<Nuake::TransformComponent>().Translation = Nuake::Vector3(-2, 0, -2);
|
||||
auto& camComponent = camera.AddComponent<Nuake::CameraComponent>();
|
||||
camComponent.CameraInstance->Fov = 44.0f;
|
||||
//auto light = PreviewScene->CreateEntity("Light");
|
||||
//auto& lightC = light.AddComponent<LightComponent>();
|
||||
//lightC.CastShadows = false;
|
||||
//lightC.Type = LightType::Directional;
|
||||
|
||||
glm::vec3 forward = glm::normalize(Vector3(0, 1, 0));
|
||||
glm::vec3 up = glm::vec3(0, 1, 0);
|
||||
|
||||
// Prevent up being colinear with forward
|
||||
if (glm::abs(glm::dot(forward, up)) > 0.999f)
|
||||
up = glm::vec3(1, 0, 0);
|
||||
|
||||
glm::vec3 right = glm::normalize(glm::cross(up, forward));
|
||||
up = glm::cross(forward, right);
|
||||
|
||||
glm::mat3 rotationMatrix(right, up, forward);
|
||||
|
||||
//auto& lightT = light.GetComponent<TransformComponent>();
|
||||
//lightT.GlobalRotation = glm::quat_cast(rotationMatrix);
|
||||
|
||||
auto sphere = PreviewScene->CreateEntity("Sphere");
|
||||
auto& modelComponent = sphere.AddComponent<Nuake::ModelComponent>();
|
||||
auto& sphereT = sphere.GetComponent<TransformComponent>();
|
||||
sphereT.Translation = { 1, 0, 0 };
|
||||
const std::vector<Nuake::Vertex> quadVertices
|
||||
{
|
||||
{ Vector3(-0.5f, 0.5f, 0.0f), 0.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(0.5f, 0.5f, 0.0f), 1.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(-0.5f, -0.5f, 0.0f), 0.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(0.5f, -0.5f, 0.0f), 1.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(-0.5f, -0.5f, 0.0f), 0.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(0.5f, 0.5f, 0.0f), 1.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) }
|
||||
};
|
||||
|
||||
const std::vector<uint32_t> quadIndices
|
||||
{
|
||||
5, 4, 3, 2, 1, 0
|
||||
};
|
||||
|
||||
auto meshQuad = CreateRef<Mesh>();
|
||||
meshQuad->AddSurface(quadVertices, quadIndices);
|
||||
|
||||
quadModel = CreateRef<Model>();
|
||||
quadModel->AddMesh(meshQuad);
|
||||
ResourceManager::RegisterResource(quadModel);
|
||||
|
||||
// Sphere
|
||||
const int sectorCount = 32;
|
||||
const int stackCount = 16;
|
||||
const float radius = 0.5f;
|
||||
|
||||
std::vector<Nuake::Vertex> sphereVertices;
|
||||
std::vector<uint32_t> sphereIndices;
|
||||
|
||||
for (int i = 0; i <= stackCount; ++i)
|
||||
{
|
||||
float stackAngle = glm::pi<float>() / 2 - i * glm::pi<float>() / stackCount;
|
||||
float xy = radius * cosf(stackAngle);
|
||||
float z = radius * sinf(stackAngle);
|
||||
|
||||
for (int j = 0; j <= sectorCount; ++j)
|
||||
{
|
||||
float sectorAngle = j * 2.0f * glm::pi<float>() / sectorCount;
|
||||
|
||||
float x = xy * cosf(sectorAngle);
|
||||
float y = xy * sinf(sectorAngle);
|
||||
Vector3 position = Vector3(x, y, z);
|
||||
Vector3 normal = glm::normalize(position);
|
||||
|
||||
// Collapse seam at the poles
|
||||
float u = (i == 0 || i == stackCount) ? 0.5f : (float)j / sectorCount;
|
||||
float v = 1.0f - (float)i / stackCount;
|
||||
|
||||
Vector4 tangent = Vector4(1, 0, 0, 0);
|
||||
Vector4 bitangent = Vector4(0, 1, 0, 0);
|
||||
|
||||
sphereVertices.push_back({ position, u, normal, v, tangent, bitangent });
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < stackCount; ++i)
|
||||
{
|
||||
int k1 = i * (sectorCount + 1);
|
||||
int k2 = k1 + sectorCount + 1;
|
||||
|
||||
for (int j = 0; j < sectorCount; ++j, ++k1, ++k2)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
sphereIndices.push_back(k1);
|
||||
sphereIndices.push_back(k2);
|
||||
sphereIndices.push_back(k1 + 1);
|
||||
}
|
||||
|
||||
if (i != (stackCount - 1))
|
||||
{
|
||||
sphereIndices.push_back(k1 + 1);
|
||||
sphereIndices.push_back(k2);
|
||||
sphereIndices.push_back(k2 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto mesh = CreateRef<Mesh>();
|
||||
mesh->AddSurface(sphereVertices, sphereIndices);
|
||||
|
||||
sphereModel = CreateRef<Model>();
|
||||
sphereModel->AddMesh(mesh);
|
||||
ResourceManager::RegisterResource(sphereModel);
|
||||
modelComponent.ModelResource = sphereModel->ID;
|
||||
|
||||
const float boxSize = 0.33f;
|
||||
const std::vector<Nuake::Vertex> boxVertices =
|
||||
{
|
||||
// Front face
|
||||
{ Vector3(-boxSize, -boxSize, boxSize), 0.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(boxSize, -boxSize, boxSize), 1.0f, Vector3(0, 0, 1), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(boxSize, boxSize, boxSize), 1.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(-boxSize, boxSize, boxSize), 0.0f, Vector3(0, 0, 1), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
|
||||
// Back face
|
||||
{ Vector3(-boxSize, -boxSize, -boxSize), 1.0f, Vector3(0, 0, -1), 0.0f, Vector4(-1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(-boxSize, boxSize, -boxSize), 1.0f, Vector3(0, 0, -1), 1.0f, Vector4(-1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(boxSize, boxSize, -boxSize), 0.0f, Vector3(0, 0, -1), 1.0f, Vector4(-1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(boxSize, -boxSize, -boxSize), 0.0f, Vector3(0, 0, -1), 0.0f, Vector4(-1, 0, 0, 0), Vector4(0, 1, 0, 0) },
|
||||
|
||||
// Left face
|
||||
{ Vector3(-boxSize, -boxSize, -boxSize), 0.0f, Vector3(-1, 0, 0), 0.0f, Vector4(0, 0, 1, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(-boxSize, -boxSize, boxSize), 1.0f, Vector3(-1, 0, 0), 0.0f, Vector4(0, 0, 1, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(-boxSize, boxSize, boxSize), 1.0f, Vector3(-1, 0, 0), 1.0f, Vector4(0, 0, 1, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(-boxSize, boxSize, -boxSize), 0.0f, Vector3(-1, 0, 0), 1.0f, Vector4(0, 0, 1, 0), Vector4(0, 1, 0, 0) },
|
||||
|
||||
// Right face
|
||||
{ Vector3(boxSize, -boxSize, -boxSize), 1.0f, Vector3(1, 0, 0), 0.0f, Vector4(0, 0, -1, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(boxSize, boxSize, -boxSize), 1.0f, Vector3(1, 0, 0), 1.0f, Vector4(0, 0, -1, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(boxSize, boxSize, boxSize), 0.0f, Vector3(1, 0, 0), 1.0f, Vector4(0, 0, -1, 0), Vector4(0, 1, 0, 0) },
|
||||
{ Vector3(boxSize, -boxSize, boxSize), 0.0f, Vector3(1, 0, 0), 0.0f, Vector4(0, 0, -1, 0), Vector4(0, 1, 0, 0) },
|
||||
|
||||
// Top face
|
||||
{ Vector3(-boxSize, boxSize, -boxSize), 0.0f, Vector3(0, 1, 0), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 0, -1, 0) },
|
||||
{ Vector3(-boxSize, boxSize, boxSize), 0.0f, Vector3(0, 1, 0), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 0, -1, 0) },
|
||||
{ Vector3(boxSize, boxSize, boxSize), 1.0f, Vector3(0, 1, 0), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 0, -1, 0) },
|
||||
{ Vector3(boxSize, boxSize, -boxSize), 1.0f, Vector3(0, 1, 0), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 0, -1, 0) },
|
||||
|
||||
// Bottom face
|
||||
{ Vector3(-boxSize, -boxSize, -boxSize), 1.0f, Vector3(0, -1, 0), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 0, 1, 0) },
|
||||
{ Vector3(boxSize, -boxSize, -boxSize), 0.0f, Vector3(0, -1, 0), 0.0f, Vector4(1, 0, 0, 0), Vector4(0, 0, 1, 0) },
|
||||
{ Vector3(boxSize, -boxSize, boxSize), 0.0f, Vector3(0, -1, 0), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 0, 1, 0) },
|
||||
{ Vector3(-boxSize, -boxSize, boxSize), 1.0f, Vector3(0, -1, 0), 1.0f, Vector4(1, 0, 0, 0), Vector4(0, 0, 1, 0) },
|
||||
};
|
||||
|
||||
const std::vector<uint32_t> boxIndices =
|
||||
{
|
||||
// Front
|
||||
0, 1, 2, 2, 3, 0,
|
||||
// Back
|
||||
4, 5, 6, 6, 7, 4,
|
||||
// Left
|
||||
8, 9,10,10,11, 8,
|
||||
// Right
|
||||
12,13,14,14,15,12,
|
||||
// Top
|
||||
16,17,18,18,19,16,
|
||||
// Bottom
|
||||
20,21,22,22,23,20
|
||||
};
|
||||
|
||||
auto meshBox = CreateRef<Mesh>();
|
||||
meshBox->AddSurface(boxVertices, boxIndices);
|
||||
|
||||
cubeModel = CreateRef<Model>();
|
||||
cubeModel->AddMesh(meshBox);
|
||||
ResourceManager::RegisterResource(cubeModel);
|
||||
modelComponent.ModelResource = cubeModel->ID;
|
||||
|
||||
auto& vkRenderer = Nuake::VkRenderer::Get();
|
||||
const UUID viewId = camComponent.CameraInstance->ID;
|
||||
|
||||
SceneViewport = vkRenderer.CreateViewport(viewId, {200, 200});
|
||||
SceneViewport->GetOnDebugDraw().AddStatic([](DebugCmd& cmd) {
|
||||
Matrix4 transform = Matrix4(1.0f);
|
||||
//cmd.DrawQuad(transform);
|
||||
});
|
||||
SceneViewport->GetOnLineDraw().AddStatic([](DebugLineCmd& cmd) {
|
||||
Matrix4 transform = Matrix4(1.0f);
|
||||
|
||||
auto cam = cmd.GetScene()->GetEntity("Camera");
|
||||
auto& camc = cam.GetComponent<CameraComponent>();
|
||||
auto& cami = camc.CameraInstance;
|
||||
auto proj = cami->GetPerspective();
|
||||
auto view = cami->GetTransform();
|
||||
//cmd.DrawSphere(proj * view * transform, { 1, 0, 0, 1 }, 2.0f, false);
|
||||
});
|
||||
|
||||
//PreviewScene->GetEnvironment()->AmbientColor = { 0, 0, 0, 0 };
|
||||
vkRenderer.RegisterSceneViewport(PreviewScene, SceneViewport->GetID());
|
||||
}
|
||||
|
||||
void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
{
|
||||
using namespace Nuake;
|
||||
|
||||
auto& t = PreviewScene->GetEntity("Camera").GetComponent<CameraComponent>();
|
||||
auto ent = PreviewScene->GetEntity("Sphere");
|
||||
|
||||
RID shape;
|
||||
switch (currentShape)
|
||||
{
|
||||
case Shapes::Quad:
|
||||
{
|
||||
shape = quadModel->ID;
|
||||
break;
|
||||
}
|
||||
case Shapes::Sphere:
|
||||
{
|
||||
shape = sphereModel->ID;
|
||||
break;
|
||||
}
|
||||
case Shapes::Cube:
|
||||
{
|
||||
shape = cubeModel->ID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shape.Get<Model>()->GetMeshes()[0]->SetMaterial(material);
|
||||
|
||||
ent.GetComponent<ModelComponent>().ModelResource = shape;
|
||||
|
||||
auto& cam = Engine::GetCurrentScene()->m_EditorCamera;
|
||||
|
||||
std::string materialTitle = material->Path;
|
||||
{
|
||||
UIFont boldfont = UIFont(Fonts::SubTitle);
|
||||
@@ -36,6 +292,130 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
}
|
||||
}
|
||||
|
||||
ImVec2 previewSize = {ImGui::GetContentRegionAvail().x, 200 };
|
||||
Vector2 viewportPanelSize = glm::vec2(previewSize.x, previewSize.y);
|
||||
static float yaw = 0.0f; // Horizontal angle in radians
|
||||
static float pitch = 0.0f; // Vertical angle in radians
|
||||
static float actualYaw = 0.0f;
|
||||
static float actualPitch = 0.0f;
|
||||
static Vector3 actualPos = { 0, 0, 0 };
|
||||
|
||||
static float distance = 1.5f; // Distance from origin
|
||||
const float yawSpeed = 0.01f;
|
||||
const float pitchSpeed = 0.01f;
|
||||
static Vector3 camPosition = Vector3(1.5, 0, 0);
|
||||
t.CameraInstance->OnWindowResize(previewSize.x, previewSize.y);
|
||||
SceneViewport->QueueResize({ previewSize.x, previewSize.y });
|
||||
ImGui::BeginChild("MaterialPreview", previewSize);
|
||||
{
|
||||
auto cursorPos = ImGui::GetCursorPos();
|
||||
|
||||
if (ImGui::BeginPopup("shapes_popup"))
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100);
|
||||
|
||||
bool isActive = currentShape == Shapes::Sphere;
|
||||
if (isActive)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button((std::string(ICON_FA_CIRCLE) + " Sphere").c_str()))
|
||||
{
|
||||
currentShape = Shapes::Sphere;
|
||||
}
|
||||
|
||||
Nuake::UI::Tooltip("Sphere");
|
||||
if (isActive)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
isActive = currentShape == Shapes::Cube;
|
||||
if (isActive)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button((std::string(ICON_FA_CUBE) + " Cube").c_str()))
|
||||
{
|
||||
currentShape = Shapes::Cube;
|
||||
}
|
||||
|
||||
UI::Tooltip("Cube");
|
||||
if (isActive)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
isActive = currentShape == Shapes::Quad;
|
||||
if (isActive)
|
||||
{
|
||||
Color color = Engine::GetProject()->Settings.PrimaryColor;
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
|
||||
}
|
||||
|
||||
if (ImGui::Button((std::string(ICON_FA_SQUARE) + " Plane").c_str()))
|
||||
{
|
||||
currentShape = Shapes::Quad;
|
||||
}
|
||||
|
||||
UI::Tooltip("Plane");
|
||||
if (isActive)
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
|
||||
{
|
||||
ImVec2 delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Left);
|
||||
yaw -= delta.x * yawSpeed;
|
||||
pitch += delta.y * pitchSpeed;
|
||||
|
||||
// Clamp pitch to prevent flipping
|
||||
pitch = std::clamp(pitch, -glm::half_pi<float>() + 0.01f, glm::half_pi<float>() - 0.01f);
|
||||
|
||||
ImGui::ResetMouseDragDelta(ImGuiMouseButton_Left); // Prevents accumulating deltas
|
||||
}
|
||||
|
||||
VkDescriptorSet textureDesc = SceneViewport->GetRenderTarget()->GetImGuiDescriptorSet();
|
||||
ImGui::Image(textureDesc, ImGui::GetContentRegionAvail(), {0, 1}, {1, 0});
|
||||
ImGui::SetCursorPos(cursorPos);
|
||||
|
||||
if (ImGui::Button(ICON_FA_SHAPES, ImVec2(30, 28)))
|
||||
{
|
||||
ImGui::OpenPopup("shapes_popup");
|
||||
}
|
||||
|
||||
UI::Tooltip("Preview Shape");
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
actualYaw = glm::mix(actualYaw, yaw, 20.0f * Engine::GetTimestep());
|
||||
actualPitch = glm::mix(actualPitch, pitch, 20.0f * Engine::GetTimestep());
|
||||
|
||||
camPosition.x = distance * cosf(actualPitch) * sinf(actualYaw);
|
||||
camPosition.y = distance * sinf(actualPitch);
|
||||
camPosition.z = distance * cosf(actualPitch) * cosf(actualYaw);
|
||||
|
||||
actualPos = glm::mix(actualPos, camPosition, 20.0f * Engine::GetTimestep());
|
||||
|
||||
Vector3 target = Vector3(0, 0, 0);
|
||||
Vector3 direction = glm::normalize(target - camPosition);
|
||||
|
||||
t.CameraInstance->Translation = { camPosition };
|
||||
t.CameraInstance->SetDirection(direction);
|
||||
bool flagsHeaderOpened;
|
||||
{
|
||||
UIFont boldfont = UIFont(Fonts::Bold);
|
||||
@@ -87,79 +467,141 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
|
||||
if (AlbedoOpened)
|
||||
{
|
||||
ImGui::BeginChild("##albedo", TexturePanelSize, true);
|
||||
ImGui::BeginTable("##Flags", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp);
|
||||
{
|
||||
ImTextureID textureID = 0;
|
||||
if (material->HasAlbedo())
|
||||
ImGui::TableSetupColumn("name", 0, 0.3f);
|
||||
ImGui::TableSetupColumn("set", 0, 0.6f);
|
||||
ImGui::TableSetupColumn("reset", 0, 0.1f);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
{
|
||||
auto vkTexture = GPUResources::Get().GetTexture(material->AlbedoImage);
|
||||
|
||||
textureID = (ImTextureID)vkTexture->GetImGuiDescriptorSet();
|
||||
ImGui::Text("Color");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
Vector3 materialColor = material->data.m_AlbedoColor;
|
||||
ImVec4 color = { materialColor.r, materialColor.g, materialColor.b, 1.0 };
|
||||
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
ImGui::ColorEdit3("##materialAlbedoColor", &material->data.m_AlbedoColor.r, ImGuiColorEditFlags_NoInputs);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Reset
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image1"), (ImTextureID)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
ImGui::Text("Texture");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImTextureID textureID = 0;
|
||||
if (material->HasAlbedo())
|
||||
{
|
||||
material->SetAlbedo(TextureManager::Get()->GetTexture(texture));
|
||||
}
|
||||
}
|
||||
auto vkTexture = GPUResources::Get().GetTexture(material->AlbedoImage);
|
||||
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
if (ImGui::MenuItem("Clear Texture"))
|
||||
textureID = (ImTextureID)vkTexture->GetImGuiDescriptorSet();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image1"), (ImTextureID)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
material->m_Albedo = nullptr;
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
{
|
||||
material->SetAlbedo(TextureManager::Get()->GetTexture(texture));
|
||||
}
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::ColorEdit3("Color", &material->data.m_AlbedoColor.r);
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
if (ImGui::MenuItem("Clear Texture"))
|
||||
{
|
||||
material->m_Albedo = nullptr;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Reset
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Normal", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::BeginChild("##normal", TexturePanelSize, true);
|
||||
ImGui::BeginTable("##Flags", 3, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingStretchProp);
|
||||
{
|
||||
uint32_t textureID = 0;
|
||||
if (material->HasNormal())
|
||||
ImGui::TableSetupColumn("name", 0, 0.3f);
|
||||
ImGui::TableSetupColumn("set", 0, 0.6f);
|
||||
ImGui::TableSetupColumn("reset", 0, 0.1f);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
static bool normalEnabled = true;
|
||||
{
|
||||
textureID = material->m_Normal->GetID();
|
||||
ImGui::Text("Enabled");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Checkbox("##normalEnabled", &normalEnabled);
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
// Reset
|
||||
ImGui::TableNextColumn();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
if (!normalEnabled)
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
|
||||
{
|
||||
ImGui::Text("Texture");
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImTextureID textureID = 0;
|
||||
if (material->HasNormal())
|
||||
{
|
||||
material->SetNormal(TextureManager::Get()->GetTexture(texture));
|
||||
auto vkTexture = GPUResources::Get().GetTexture(material->NormalImage);
|
||||
textureID = (ImTextureID)vkTexture->GetImGuiDescriptorSet();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
{
|
||||
std::string texture = FileDialog::OpenFile("*.png | *.jpg");
|
||||
if (texture != "")
|
||||
{
|
||||
material->SetNormal(TextureManager::Get()->GetTexture(texture));
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
if (ImGui::MenuItem("Clear Texture"))
|
||||
{
|
||||
material->m_Normal = nullptr;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
if (!normalEnabled)
|
||||
{
|
||||
if (ImGui::MenuItem("Clear Texture"))
|
||||
{
|
||||
material->m_Normal = nullptr;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("AO", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::BeginChild("##ao", TexturePanelSize, true);
|
||||
{
|
||||
uint32_t textureID = 0;
|
||||
ImTextureID textureID = 0;
|
||||
if (material->HasAO())
|
||||
{
|
||||
textureID = material->m_AO->GetID();
|
||||
auto vkTexture = GPUResources::Get().GetTexture(material->AOImage);
|
||||
textureID = (ImTextureID)vkTexture->GetImGuiDescriptorSet();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image2"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(1, 1, 1, 1), ImVec4(1, 1, 1, 1)))
|
||||
@@ -190,10 +632,11 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
{
|
||||
ImGui::BeginChild("##metalness", TexturePanelSize, true);
|
||||
{
|
||||
uint32_t textureID = 0;
|
||||
ImTextureID textureID = 0;
|
||||
if (material->HasMetalness())
|
||||
{
|
||||
textureID = material->m_Metalness->GetID();
|
||||
auto vkTexture = GPUResources::Get().GetTexture(material->MetalnessImage);
|
||||
textureID = (ImTextureID)vkTexture->GetImGuiDescriptorSet();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image4"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
@@ -224,10 +667,11 @@ void MaterialEditor::Draw(Ref<Nuake::Material> material)
|
||||
{
|
||||
ImGui::BeginChild("##roughness", TexturePanelSize, true);
|
||||
{
|
||||
uint32_t textureID = 0;
|
||||
ImTextureID textureID = 0;
|
||||
if (material->HasRoughness())
|
||||
{
|
||||
textureID = material->m_Roughness->GetID();
|
||||
auto vkTexture = GPUResources::Get().GetTexture(material->RoughnessImage);
|
||||
textureID = (ImTextureID)vkTexture->GetImGuiDescriptorSet();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image5"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 0), ImVec4(1, 1, 1, 1)))
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
#pragma once
|
||||
#include <Nuake/Core/Core.h>
|
||||
#include <Nuake/Rendering/Textures/Material.h>
|
||||
#include <Nuake/Scene/Scene.h>
|
||||
|
||||
#include "Nuake/Rendering/Vulkan/SceneViewport.h"
|
||||
class MaterialEditor
|
||||
{
|
||||
private:
|
||||
Ref<Nuake::Scene> PreviewScene;
|
||||
Ref<Nuake::Viewport> SceneViewport;
|
||||
public:
|
||||
MaterialEditor() = default;
|
||||
MaterialEditor();
|
||||
~MaterialEditor() = default;
|
||||
|
||||
void Draw(Ref<Nuake::Material> material);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
ModelResourceInspector::ModelResourceInspector(Ref<Nuake::Model> model)
|
||||
{
|
||||
_model = model;
|
||||
|
||||
}
|
||||
|
||||
void ModelResourceInspector::Draw()
|
||||
@@ -19,7 +20,7 @@ void ModelResourceInspector::Draw()
|
||||
std::string childId = "materialEditor" + std::to_string(i);
|
||||
ImGui::BeginChild(childId.c_str(), ImVec2(0, 0), false);
|
||||
{
|
||||
MaterialEditor editor;
|
||||
static MaterialEditor editor;
|
||||
editor.Draw(_model->GetMeshes().at(i)->GetMaterial());
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <Nuake/UI/ImUI.h>
|
||||
#include "../../../Misc/InterfaceFonts.h"
|
||||
#include <Nuake/Resource/Bakers/AssetBakerManager.h>
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
@@ -269,7 +270,7 @@ void FileBrowserWidget::Draw()
|
||||
{
|
||||
if (searchQuery.empty() || f->GetName().find(String::Sanitize(searchQuery)) != std::string::npos)
|
||||
{
|
||||
if (f->GetFileType() == FileType::Unknown || f->GetFileType() == FileType::Assembly)
|
||||
if ((f->GetFileType() == FileType::Unknown && !AssetBakerManager::Get().IsBakable(f)) || f->GetFileType() == FileType::Assembly)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -781,6 +782,14 @@ void FileBrowserWidget::DrawFile(Ref<Nuake::File> file, uint32_t drawId)
|
||||
shouldOpenScene = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (AssetBakerManager::Get().IsBakable(file))
|
||||
{
|
||||
if (ImGui::MenuItem("Rebake"))
|
||||
{
|
||||
AssetBakerManager::Get().OnNewAssetDetected(file);
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "Nuake/Scene/Components.h"
|
||||
|
||||
#include "Nuake/UI/ImUI.h"
|
||||
#include "../../../ComponentsPanel/MaterialEditor.h"
|
||||
|
||||
#include <Nuake/Resource/SkyResource.h>
|
||||
#include <Nuake/FileSystem/FileDialog.h>
|
||||
@@ -238,7 +237,6 @@ void SelectionPropertyWidget::DrawFile(Ref<Nuake::File> file)
|
||||
{
|
||||
case FileType::Material:
|
||||
{
|
||||
MaterialEditor matEditor;
|
||||
matEditor.Draw(std::static_pointer_cast<Material>(selectedResource));
|
||||
break;
|
||||
}
|
||||
@@ -1665,14 +1663,14 @@ void SelectionPropertyWidget::DrawMaterialPanel(Ref<Nuake::Material> material)
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Normal", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
if (ImGui::CollapsingHeader("Normal", ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
ImGui::BeginChild("##normal", TexturePanelSize, true);
|
||||
{
|
||||
uint32_t textureID = 0;
|
||||
if (material->HasNormal())
|
||||
{
|
||||
textureID = material->m_Normal->GetID();
|
||||
textureID = material->m_Normal->GetID();
|
||||
}
|
||||
|
||||
if (ImGui::ImageButtonEx(ImGui::GetCurrentWindow()->GetID("#image3"), (void*)textureID, ImVec2(80, 80), ImVec2(0, 1), ImVec2(1, 0), ImVec4(0, 0, 0, 1), ImVec4(1, 1, 1, 1)))
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "../../EditorSelectionPanel.h"
|
||||
|
||||
#include "../../../misc/AnimatedValue.h"
|
||||
#include "../../../ComponentsPanel/MaterialEditor.h"
|
||||
|
||||
class EditorContext;
|
||||
|
||||
@@ -12,6 +13,7 @@ using DrawFieldTypeFn = std::function<void(entt::meta_data& fieldMeta, entt::met
|
||||
class SelectionPropertyWidget : public IEditorWidget
|
||||
{
|
||||
private:
|
||||
MaterialEditor matEditor;
|
||||
TransformPanel transformPanel;
|
||||
MeshPanel meshPanel;
|
||||
SkinnedMeshPanel skinnedMeshPanel;
|
||||
|
||||
@@ -35,10 +35,7 @@ Ref<File> GLTFBaker::Bake(const Ref<File>& file)
|
||||
|
||||
const std::string absolutePath = file->GetAbsolutePath();
|
||||
auto importFlags =
|
||||
aiProcess_Triangulate |
|
||||
aiProcess_GenSmoothNormals |
|
||||
aiProcess_FixInfacingNormals |
|
||||
aiProcess_CalcTangentSpace;
|
||||
aiProcessPreset_TargetRealtime_Fast;
|
||||
const aiScene* scene = importer.ReadFile(absolutePath, importFlags);
|
||||
|
||||
if(!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // Assimp failed
|
||||
@@ -88,22 +85,22 @@ Ref<File> GLTFBaker::Bake(const Ref<File>& file)
|
||||
|
||||
if (!materialData.normal.empty())
|
||||
{
|
||||
material->SetNormal(absolutePath + "/../" + materialData.normal);
|
||||
material->SetNormal(FileSystem::AbsoluteToRelative(absolutePath + "/../" + materialData.normal));
|
||||
}
|
||||
|
||||
if (!materialData.ao.empty())
|
||||
{
|
||||
material->SetAO(absolutePath + "/../" + materialData.ao);
|
||||
material->SetAO(FileSystem::AbsoluteToRelative(absolutePath + "/../" + materialData.ao));
|
||||
}
|
||||
|
||||
if (!materialData.metallic.empty())
|
||||
{
|
||||
material->SetMetalness(absolutePath + "/../" + materialData.metallic);
|
||||
material->SetMetalness(FileSystem::AbsoluteToRelative(absolutePath + "/../" + materialData.metallic));
|
||||
}
|
||||
|
||||
if (!materialData.roughness.empty())
|
||||
{
|
||||
material->SetRoughness(absolutePath + "/../" + materialData.roughness);
|
||||
material->SetRoughness(FileSystem::AbsoluteToRelative(absolutePath + "/../" + materialData.roughness));
|
||||
}
|
||||
|
||||
ResourceManager::RegisterResource(material);
|
||||
|
||||
@@ -161,22 +161,72 @@ namespace Nuake
|
||||
|
||||
void Material::SetAO(const std::string ao)
|
||||
{
|
||||
if (FileSystem::FileExists(ao))
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> image = CreateRef<VulkanImage>(FileSystem::RelativeToAbsolute(ao));
|
||||
if (resources.AddTexture(image))
|
||||
{
|
||||
AOImage = image->GetID();
|
||||
}
|
||||
|
||||
Ref<Texture> aoTexture = TextureManager::Get()->GetTexture(FileSystem::RelativeToAbsolute(ao));
|
||||
SetAO(aoTexture);
|
||||
}
|
||||
|
||||
m_AO = CreateRef<Texture>(ao);
|
||||
}
|
||||
|
||||
void Material::SetMetalness(const std::string metalness)
|
||||
{
|
||||
if (FileSystem::FileExists(metalness))
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> image = CreateRef<VulkanImage>(FileSystem::RelativeToAbsolute(metalness));
|
||||
if (resources.AddTexture(image))
|
||||
{
|
||||
MetalnessImage = image->GetID();
|
||||
}
|
||||
|
||||
Ref<Texture> aoTexture = TextureManager::Get()->GetTexture(FileSystem::RelativeToAbsolute(metalness));
|
||||
SetMetalness(aoTexture);
|
||||
}
|
||||
|
||||
m_Metalness = CreateRef<Texture>(metalness);
|
||||
}
|
||||
|
||||
void Material::SetRoughness(const std::string roughness)
|
||||
{
|
||||
if (FileSystem::FileExists(roughness))
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> image = CreateRef<VulkanImage>(FileSystem::RelativeToAbsolute(roughness));
|
||||
if (resources.AddTexture(image))
|
||||
{
|
||||
RoughnessImage = image->GetID();
|
||||
}
|
||||
|
||||
Ref<Texture> aoTexture = TextureManager::Get()->GetTexture(FileSystem::RelativeToAbsolute(roughness));
|
||||
SetRoughness(aoTexture);
|
||||
}
|
||||
|
||||
m_Roughness = CreateRef<Texture>(roughness);
|
||||
}
|
||||
|
||||
void Material::SetNormal(const std::string normal)
|
||||
{
|
||||
m_Normal = CreateRef<Texture>(normal);
|
||||
if (FileSystem::FileExists(normal))
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> image = CreateRef<VulkanImage>(FileSystem::RelativeToAbsolute(normal));
|
||||
if (resources.AddTexture(image))
|
||||
{
|
||||
NormalImage = image->GetID();
|
||||
}
|
||||
|
||||
Ref<Texture> aoTexture = TextureManager::Get()->GetTexture(FileSystem::RelativeToAbsolute(normal));
|
||||
SetNormal(aoTexture);
|
||||
}
|
||||
}
|
||||
|
||||
void Material::SetDisplacement(const std::string displacement)
|
||||
|
||||
@@ -117,19 +117,19 @@ namespace Nuake
|
||||
}
|
||||
void SetAlbedo(Ref<Texture> texture) { m_Albedo = texture; }
|
||||
|
||||
bool HasAO() { return m_AO != nullptr; }
|
||||
bool HasAO() { return (m_AO != nullptr || AOImage != UUID(0)); }
|
||||
void SetAO(const std::string albedo);
|
||||
void SetAO(Ref<Texture> texture) { m_AO = texture; }
|
||||
|
||||
bool HasMetalness() { return m_Metalness != nullptr; }
|
||||
bool HasMetalness() { return (m_Metalness != nullptr || MetalnessImage != UUID(0)); }
|
||||
void SetMetalness(const std::string albedo);
|
||||
void SetMetalness(Ref<Texture> texture) { m_Metalness = texture; }
|
||||
|
||||
bool HasRoughness() { return m_Roughness != nullptr; }
|
||||
bool HasRoughness() { return (m_Roughness != nullptr || RoughnessImage != UUID(0)); }
|
||||
void SetRoughness(const std::string albedo);
|
||||
void SetRoughness(Ref<Texture> texture) { m_Roughness = texture; }
|
||||
|
||||
bool HasNormal() { return m_Normal != nullptr; }
|
||||
bool HasNormal() { return (m_Normal != nullptr || NormalImage != UUID(0)); }
|
||||
void SetNormal(const std::string albedo);
|
||||
void SetNormal(Ref<Texture> texture) { m_Normal = texture; }
|
||||
|
||||
@@ -176,6 +176,7 @@ namespace Nuake
|
||||
{
|
||||
j["Albedo"] = this->m_Albedo->Serialize();
|
||||
}
|
||||
|
||||
Vector3 AlbedoColor = data.m_AlbedoColor;
|
||||
SERIALIZE_VEC3(AlbedoColor);
|
||||
|
||||
@@ -328,6 +329,7 @@ namespace Nuake
|
||||
{
|
||||
const auto& texturePath = j["AO"]["Path"];
|
||||
const std::string absolutePath = FileSystem::RelativeToAbsolute(texturePath);
|
||||
|
||||
if (FileSystem::FileExists(texturePath))
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
@@ -336,46 +338,66 @@ namespace Nuake
|
||||
{
|
||||
AOImage = image->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Texture> aoTexture = TextureManager::Get()->GetTexture(absolutePath);
|
||||
SetAO(aoTexture);
|
||||
Ref<Texture> normalTexture = TextureManager::Get()->GetTexture(absolutePath);
|
||||
SetAO(normalTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> missingTexture = TextureManager::Get()->GetTexture2("missing_texture");
|
||||
AOImage = missingTexture->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
if (j.contains("Metalness"))
|
||||
{
|
||||
const auto& texturePath = j["Metalness"]["Path"];
|
||||
const std::string absolutePath = FileSystem::RelativeToAbsolute(texturePath);
|
||||
|
||||
if (FileSystem::FileExists(texturePath))
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> image = CreateRef<VulkanImage>(absolutePath);
|
||||
if (resources.AddTexture(image))
|
||||
{
|
||||
MetalnessImage = image->GetID();
|
||||
AOImage = image->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Texture> metalTexture = TextureManager::Get()->GetTexture(absolutePath);
|
||||
SetMetalness(metalTexture);
|
||||
Ref<Texture> normalTexture = TextureManager::Get()->GetTexture(absolutePath);
|
||||
SetMetalness(normalTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> missingTexture = TextureManager::Get()->GetTexture2("missing_texture");
|
||||
MetalnessImage = missingTexture->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
if (j.contains("Roughness"))
|
||||
{
|
||||
const auto& texturePath = j["Roughness"]["Path"];
|
||||
const std::string absolutePath = FileSystem::RelativeToAbsolute(texturePath);
|
||||
|
||||
if (FileSystem::FileExists(texturePath))
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> image = CreateRef<VulkanImage>(absolutePath);
|
||||
if (resources.AddTexture(image))
|
||||
{
|
||||
RoughnessImage = image->GetID();
|
||||
AOImage = image->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<Texture> metalTexture = TextureManager::Get()->GetTexture(absolutePath);
|
||||
SetRoughness(metalTexture);
|
||||
Ref<Texture> normalTexture = TextureManager::Get()->GetTexture(absolutePath);
|
||||
SetRoughness(normalTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
GPUResources& resources = GPUResources::Get();
|
||||
Ref<VulkanImage> missingTexture = TextureManager::Get()->GetTexture2("missing_texture");
|
||||
RoughnessImage = missingTexture->GetID();
|
||||
}
|
||||
}
|
||||
|
||||
if (j.contains("Displacement"))
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <Tracy.hpp>
|
||||
#include "DebugCmd.h"
|
||||
#include <random>
|
||||
#include <Nuake/Scene/Components/ParticleEmitterComponent.h>
|
||||
|
||||
using namespace Nuake;
|
||||
|
||||
@@ -405,6 +406,31 @@ void SceneRenderPipeline::RecreatePipeline()
|
||||
cmd.DrawIndexed(vkMesh->GetIndexBuffer()->GetSize() / sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
auto particleView = scene->m_Registry.view<TransformComponent, ParticleEmitterComponent, VisibilityComponent>();
|
||||
for (auto e : particleView)
|
||||
{
|
||||
auto [transform, particle, visibility] = particleView.get<TransformComponent, ParticleEmitterComponent, VisibilityComponent>(e);
|
||||
|
||||
if (!visibility.Visible)
|
||||
continue;
|
||||
|
||||
if (particle.resFile.dirty)
|
||||
{
|
||||
particle.resFile.dirty = false;
|
||||
|
||||
if (particle.resFile.Exist())
|
||||
{
|
||||
Ref<Nuake::Material> material = Nuake::ResourceLoader::LoadMaterial(particle.resFile.GetRelativePath());
|
||||
particle.ParticleMaterial = material;
|
||||
}
|
||||
}
|
||||
|
||||
if (particle.ParticleMaterial == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
auto& ssaoPass = GBufferPipeline.AddPass("SSAOPass");
|
||||
@@ -927,16 +953,7 @@ Ref<VulkanImage> SceneRenderPipeline::ResizeImage(PassRenderContext& ctx, Ref<Vu
|
||||
// Register to resource manager
|
||||
GPUResources& gpuResources = GPUResources::Get();
|
||||
gpuResources.AddTexture(newAttachment);
|
||||
|
||||
using CleanUpFunc = std::function<void()>;
|
||||
using CleanUpStack = std::stack<CleanUpFunc>;
|
||||
|
||||
CleanUpStack stack;
|
||||
stack.push([image]() {
|
||||
GPUResources& gpuResources = GPUResources::Get();
|
||||
//gpuResources.RemoveTexture(image);
|
||||
});
|
||||
//gpuResources.QueueDeletion(std::move(stack));
|
||||
gpuResources.RemoveTexture(image);
|
||||
|
||||
// We might need to do this?
|
||||
ctx.commandBuffer.TransitionImageLayout(newAttachment, VK_IMAGE_LAYOUT_GENERAL);
|
||||
|
||||
@@ -127,7 +127,7 @@ Ref<VulkanShader> ShaderCompiler::CompileShader(const std::string& path)
|
||||
|
||||
Logger::Log("Shader compilation failed: " + errorMsgStr, "DXC", CRITICAL);
|
||||
|
||||
throw std::runtime_error("Shader compilation failed: " + errorMsgStr);
|
||||
throw std::runtime_error("Shader compilation failed: " + errorMsgStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -388,6 +388,7 @@ VkDescriptorSet& VulkanImage::GetImGuiDescriptorSet()
|
||||
sampler_info.minLod = -1000;
|
||||
sampler_info.maxLod = 1000;
|
||||
sampler_info.maxAnisotropy = 1.0f;
|
||||
|
||||
VK_CALL(vkCreateSampler(VkRenderer::Get().GetDevice(), &sampler_info, nullptr, &Sampler));
|
||||
|
||||
// Create Descriptor Set using ImGUI's implementation
|
||||
|
||||
@@ -236,6 +236,11 @@ namespace Nuake
|
||||
return Device;
|
||||
}
|
||||
|
||||
VkPhysicalDevice GetPhysicalDevice() const
|
||||
{
|
||||
return GPU;
|
||||
}
|
||||
|
||||
FrameData& GetCurrentFrame()
|
||||
{
|
||||
return Frames[FrameNumber % FRAME_OVERLAP];
|
||||
|
||||
@@ -170,7 +170,7 @@ Ref<VulkanImage> GPUResources::GetTexture(const UUID& id)
|
||||
return Images[id];
|
||||
}
|
||||
|
||||
Logger::Log("Mesh with ID does not exist", "vulkan", CRITICAL);
|
||||
Logger::Log("Texture with ID does not exist", "vulkan", CRITICAL);
|
||||
return TextureManager::Get()->GetTexture2("missing_texture");
|
||||
}
|
||||
|
||||
@@ -285,13 +285,20 @@ void GPUResources::CreateBindlessLayout()
|
||||
SSAOKernelDescriptor = allocator.Allocate(device, SSAOKernelDescriptorLayout);
|
||||
|
||||
// Samplers
|
||||
VkPhysicalDeviceProperties properties{};
|
||||
vkGetPhysicalDeviceProperties(VkRenderer::Get().GetPhysicalDevice(), &properties);
|
||||
|
||||
VkSamplerCreateInfo sampler = { .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
||||
sampler.magFilter = VK_FILTER_NEAREST;
|
||||
sampler.minFilter = VK_FILTER_NEAREST;
|
||||
sampler.anisotropyEnable = VK_TRUE;
|
||||
sampler.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
|
||||
vkCreateSampler(device, &sampler, nullptr, &SamplerNearest);
|
||||
|
||||
sampler.magFilter = VK_FILTER_LINEAR;
|
||||
sampler.minFilter = VK_FILTER_LINEAR;
|
||||
sampler.anisotropyEnable = VK_TRUE;
|
||||
sampler.maxAnisotropy = properties.limits.maxSamplerAnisotropy;
|
||||
vkCreateSampler(device, &sampler, nullptr, &SamplerLinear);
|
||||
|
||||
VkDescriptorImageInfo textureInfo = {};
|
||||
|
||||
@@ -34,6 +34,11 @@ namespace Nuake
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBakable(const Ref<File>& file)
|
||||
{
|
||||
return Bakers.find(file->GetExtension()) != Bakers.end();
|
||||
}
|
||||
|
||||
void OnAssetReimport(const Ref<File>& file)
|
||||
{
|
||||
const std::string extension = file->GetExtension();
|
||||
|
||||
Reference in New Issue
Block a user