diff --git a/WRITEUP.md b/WRITEUP.md index c4a01f4..7d88c34 100644 --- a/WRITEUP.md +++ b/WRITEUP.md @@ -146,7 +146,6 @@ Here is the material generated from the above JSON example: ```cpp import VERTEX_INPUT_IMPORT; import Material; -import BRDF; import MaterialParameter; struct Placeholder: IMaterial { diff --git a/res/shaders/BasePass.slang b/res/shaders/BasePass.slang index 3c7d1b1..9c7b74a 100644 --- a/res/shaders/BasePass.slang +++ b/res/shaders/BasePass.slang @@ -30,6 +30,6 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target uint lightIndex = pLightCullingData.lightIndexList[startOffset + i]; result += pLightEnv.pointLights[lightIndex].illuminate(lightingParams, brdf); } - result += brdf.evaluateAmbient(); + result += brdf.evaluateAmbient(lightingParams.viewDir_WS); return float4(result, brdf.getAlpha()); } \ No newline at end of file diff --git a/res/shaders/EnvironmentMapping.slang b/res/shaders/EnvironmentMapping.slang index ba950b8..3545fc6 100644 --- a/res/shaders/EnvironmentMapping.slang +++ b/res/shaders/EnvironmentMapping.slang @@ -1,9 +1,40 @@ -struct VertexOutput -{ - float4 svPos : SV_Position; - float3 localPos : LOCALPOS; -}; const static float3 vertices[] = { + // Right + float3( 1, -1, 1), + float3( 1, 1, 1), + float3( 1, -1, -1), + + float3( 1, -1, -1), + float3( 1, 1, 1), + float3( 1, 1, -1), + + // Left + float3(-1, -1, -1), + float3(-1, 1, -1), + float3(-1, -1, 1), + + float3(-1, -1, 1), + float3(-1, 1, -1), + float3(-1, 1, 1), + + // Bottom + float3(-1, 1, 1), + float3(-1, 1, -1), + float3( 1, 1, 1), + + float3( 1, 1, 1), + float3(-1, 1, -1), + float3( 1, 1, -1), + + // Top + float3(-1, -1, -1), + float3(-1, -1, 1), + float3( 1, -1, -1), + + float3( 1, -1, -1), + float3(-1, -1, 1), + float3( 1, -1, 1), + // Back float3(-1, -1, 1), float3(-1, 1, 1), @@ -21,42 +52,6 @@ const static float3 vertices[] = { float3(-1, -1, -1), float3( 1, 1, -1), float3(-1, 1, -1), - - // Top - float3(-1, -1, -1), - float3(-1, -1, 1), - float3( 1, -1, -1), - - float3( 1, -1, -1), - float3(-1, -1, 1), - float3( 1, -1, 1), - - // Bottom - float3(-1, 1, 1), - float3(-1, 1, -1), - float3( 1, 1, 1), - - float3( 1, 1, 1), - float3(-1, 1, -1), - float3( 1, 1, -1), - - // Left - float3(-1, -1, -1), - float3(-1, 1, -1), - float3(-1, -1, 1), - - float3(-1, -1, 1), - float3(-1, 1, -1), - float3(-1, 1, 1), - - // Right - float3( 1, -1, 1), - float3( 1, 1, 1), - float3( 1, -1, -1), - - float3( 1, -1, -1), - float3( 1, 1, 1), - float3( 1, 1, -1), }; struct ViewParams @@ -65,31 +60,66 @@ struct ViewParams float4x4 projection; Texture2D equirectangularMap; SamplerState sampler; + TextureCube cubeMap; }; ParameterBlock pViewParams; - +struct VertexOutput +{ + float4 svPos : SV_Position; + float3 localPos : LOCALPOS; +}; [shader("vertex")] VertexOutput vertMain(uint vertexIndex : SV_VertexID, uint viewIndex : SV_ViewID) { VertexOutput output; - output.localPos = vertices[vertexIndex + 6 * viewIndex]; - output.svPos = mul(pViewParams.projection, mul(pViewParams.view[viewIndex], float4(vertices[vertexIndex], 1))); + output.localPos = vertices[vertexIndex]; + output.svPos = mul(pViewParams.projection, mul(pViewParams.view[viewIndex], float4(output.localPos, 1))); return output; } const static float2 invAtan = float2(0.1591, 0.3183); float2 sampleSphericalMap(float3 v) { - float2 uv = float2(atan(v.z / v.x), asin(v.y)); + float2 uv = float2(atan2(v.z, v.x), asin(v.y)); uv *= invAtan; uv += 0.5; return uv; } -[shader("fragment")] -float4 fragMain(float3 localPos : LOCALPOS) : SV_Target +[shader("pixel")] +float4 computeCubemap(float3 localPos : LOCALPOS) : SV_Target { float2 uv = sampleSphericalMap(normalize(localPos)); float3 color = pViewParams.equirectangularMap.Sample(pViewParams.sampler, uv).rgb; return float4(color, 1); +} + +static const float PI = 3.14159265359; +[shader("pixel")] +float4 convolveCubemap(float3 localPos : LOCALPOS) : SV_Target +{ + float3 normal = normalize(localPos); + + float3 irradiance = float3(0); + + float3 up = float3(0, 1, 0); + float3 right = normalize(cross(up, normal)); + up = normalize(cross(normal, right)); + + float sampleDelta = 0.025; + float nrSamples = 0.0f; + for(float phi = 0; phi < 2.0 * PI; phi += sampleDelta) + { + for(float theta = 0; theta < 0.5 * PI; theta += sampleDelta) + { + float3 tangentSample = float3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); + float3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal; + + irradiance += pViewParams.cubeMap.Sample(pViewParams.sampler, sampleVec).rgb * cos(theta) * sin(theta); + nrSamples++; + } + } + irradiance = PI * irradiance * (1.0 / nrSamples); + + return float4(irradiance, 1); } \ No newline at end of file diff --git a/res/shaders/lib/BRDF.slang b/res/shaders/lib/BRDF.slang deleted file mode 100644 index 612496d..0000000 --- a/res/shaders/lib/BRDF.slang +++ /dev/null @@ -1,291 +0,0 @@ -import Common; - -interface IBRDF -{ - float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor); - [mutating] void transformNormal(float3x3 tangentToWorld); - float3 getNormal(); - float3 getBaseColor(); - float3 evaluateAmbient(); - float getAlpha(); - float3 getEmissive(); -}; - -struct Phong : IBRDF -{ - float3 baseColor; - float alpha; - float3 specular; - float3 normal; - float3 ambient; - float shininess; - float3 emissive; - - __init() - { - baseColor = float3(0, 0, 0); - alpha = 1; - specular = float3(0, 0, 0); - normal = float3(0, 0, 1); - ambient = float3(0, 0, 0); - shininess = 0; - emissive = float3(0, 0, 0); - } - - float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) - { - float3 normal_WS = normal; - float3 nDotL = dot(normal_WS, lightDir_WS); - float3 r = 2 * (nDotL) * normal_WS - lightDir_WS; - float rDotV = dot(r, viewDir_WS); - - return lightColor * (baseColor * max(nDotL, 0.0)) + specular * pow(max(rDotV, 0.0), max(shininess, 1)); - } - [mutating] - void transformNormal(float3x3 tangentToWorld) - { - normal = normalize(mul(tangentToWorld, normal)); - } - float3 getNormal() - { - return normal; - } - float3 getBaseColor() - { - return baseColor; - } - float3 evaluateAmbient() - { - return ambient; - } - float getAlpha() - { - return alpha; - } - float3 getEmissive() - { - return emissive; - } -}; - -struct BlinnPhong : IBRDF -{ - float3 baseColor; - float alpha; - float3 specularColor; - float3 normal; - float shininess; - float3 ambient; - float3 emissive; - - __init() - { - baseColor = float3(0, 0, 0); - alpha = 1; - specularColor = float3(0, 0, 0); - normal = float3(0, 0, 1); - shininess = 4; - ambient = float3(0, 0, 0); - emissive = float3(0, 0, 0); - } - - float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) - { - float3 normal_WS = normal; - float diffuse = max(dot(normal_WS, lightDir_WS), 0); - float3 h = normalize(lightDir_WS + viewDir_WS); - float specular = pow(saturate(dot(normal_WS, h)), shininess); - - return (baseColor * diffuse * lightColor) + (specularColor * specular); - } - [mutating] - void transformNormal(float3x3 tangentToWorld) - { - normal = normalize(mul(tangentToWorld, normal)); - } - float3 getNormal() - { - return normal; - } - float3 getBaseColor() - { - return baseColor; - } - float3 evaluateAmbient() - { - return ambient; - } - float getAlpha() - { - return alpha; - } - float3 getEmissive() - { - return emissive; - } -}; - -struct CelShading : IBRDF -{ - float3 baseColor; - float alpha; - float3 normal; - float3 emissive; - - __init() - { - baseColor = float3(0, 0, 0); - alpha = 1; - normal = float3(0, 0, 1); - emissive = float3(0, 0, 0); - } - float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) - { - float3 normal_WS = normal; - float nDotL = dot(normal_WS, lightDir_WS); - float diffuse = max(nDotL, 0); - - float3 darkenedBase = baseColor * 0.8; - if(diffuse > 0.5) - { - return baseColor * lightColor; - } - else - { - return darkenedBase * lightColor; - } - } - [mutating] - void transformNormal(float3x3 tangentToWorld) - { - normal = normalize(mul(tangentToWorld, normal)); - } - float3 getNormal() - { - return normal; - } - float3 getBaseColor() - { - return baseColor; - } - float3 evaluateAmbient() - { - return float3(0, 0, 0); - } - float getAlpha() - { - return alpha; - } - float3 getEmissive() - { - return emissive; - } -}; - -// https://learnopengl.com/PBR/Theory -struct CookTorrance : IBRDF -{ - float3 baseColor; - float alpha; - float3 normal; - float roughness; - float metallic; - float ambientOcclusion; - float3 emissive; - - __init() - { - baseColor = float3(0, 0, 0); - alpha = 1; - normal = float3(0, 0, 1); - roughness = 0; - metallic = 0; - ambientOcclusion = 1; - emissive = float3(0, 0, 0); - } - - float TrowbridgeReitzGGX(float3 normal, float3 halfway) - { - float a_sqr = roughness * roughness; - float nDotH = max(dot(normal, halfway), 0.0); - float nDotH_sqr = nDotH * nDotH; - - float denom = (nDotH_sqr * (a_sqr - 1.0) + 1.0); - - return a_sqr / (PI * denom * denom); - } - - float SchlickGGX(float nDotV, float k) - { - return nDotV / (nDotV * (1.0 - k) + k); - } - - float Smith(float3 normal, float3 view, float3 light) - { - float k = (roughness + 1); - k = (k * k) / 8; - float nDotV = max(dot(normal, view), 0.0); - float nDotL = max(dot(normal, light), 0.0); - float ggx1 = SchlickGGX(nDotV, k); - float ggx2 = SchlickGGX(nDotL, k); - return ggx1 * ggx2; - } - - float3 FresnelSchlick(float cosTheta, float3 F0) - { - return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); - } - - float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) - { - float3 n = normal; - float3 h = normalize(lightDir_WS + viewDir_WS); - - float3 F0 = float3(0.04); - F0 = lerp(F0, baseColor, metallic); - - float3 F = FresnelSchlick(max(dot(h, viewDir_WS), 0.0), F0); - - float NDF = TrowbridgeReitzGGX(n, h); - float G = Smith(n, viewDir_WS, lightDir_WS); - - float3 num = NDF * G * F; - float denom = 4.0 * max(dot(n, viewDir_WS), 0.0) * max(dot(n, lightDir_WS), 0.0) + 0.000001; - float3 specular = num / denom; - - float3 k_s = F; - float3 k_d = float3(1.0) - k_s; - - k_d *= 1.0 - metallic; - - float nDotL = max(dot(n, lightDir_WS), 0.0); - - float3 result = (k_d * baseColor / PI + specular) * nDotL * lightColor; - return result * ambientOcclusion; - } - [mutating] - void transformNormal(float3x3 tangentToWorld) - { - normal = normalize(mul(tangentToWorld, normal)); - } - float3 getNormal() - { - return normal; - } - float3 getBaseColor() - { - return baseColor; - } - float3 evaluateAmbient() - { - return float3(0.03) * baseColor * ambientOcclusion; - } - float getAlpha() - { - return alpha; - } - float3 getEmissive() - { - return emissive; - } -}; diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index 393987c..ae2fdcf 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -1,5 +1,4 @@ import Common; -import BRDF; import MaterialParameter; interface ILightEnv @@ -28,7 +27,7 @@ struct PointLight : ILightEnv { float3 lightDir_WS = position_WS.xyz - params.position_WS; float d = length(lightDir_WS); - float illuminance = max(1 - d / colorRange.w, 0); + float illuminance = max(1 / (d * d), 0); return illuminance * brdf.evaluate(params.viewDir_WS, normalize(lightDir_WS), colorRange.xyz * position_WS.w); } @@ -65,6 +64,308 @@ struct LightEnv uint numDirectionalLights; StructuredBuffer pointLights; uint numPointLights; + TextureCube irradianceMap; + SamplerState irradianceSampler; }; layout(set=3) ParameterBlock pLightEnv; + + +interface IBRDF +{ + float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor); + [mutating] void transformNormal(float3x3 tangentToWorld); + float3 getNormal(); + float3 getBaseColor(); + float3 evaluateAmbient(float3 viewDir_WS); + float getAlpha(); + float3 getEmissive(); +}; + +struct Phong : IBRDF +{ + float3 baseColor; + float alpha; + float3 specular; + float3 normal; + float3 ambient; + float shininess; + float3 emissive; + + __init() + { + baseColor = float3(0, 0, 0); + alpha = 1; + specular = float3(0, 0, 0); + normal = float3(0, 0, 1); + ambient = float3(0, 0, 0); + shininess = 0; + emissive = float3(0, 0, 0); + } + + float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) + { + float3 normal_WS = normal; + float3 nDotL = dot(normal_WS, lightDir_WS); + float3 r = 2 * (nDotL) * normal_WS - lightDir_WS; + float rDotV = dot(r, viewDir_WS); + + return lightColor * (baseColor * max(nDotL, 0.0)) + specular * pow(max(rDotV, 0.0), max(shininess, 1)); + } + [mutating] + void transformNormal(float3x3 tangentToWorld) + { + normal = normalize(mul(tangentToWorld, normal)); + } + float3 getNormal() + { + return normal; + } + float3 getBaseColor() + { + return baseColor; + } + float3 evaluateAmbient(float3 viewDir_WS) + { + return ambient; + } + float getAlpha() + { + return alpha; + } + float3 getEmissive() + { + return emissive; + } +}; + +struct BlinnPhong : IBRDF +{ + float3 baseColor; + float alpha; + float3 specularColor; + float3 normal; + float shininess; + float3 ambient; + float3 emissive; + + __init() + { + baseColor = float3(0, 0, 0); + alpha = 1; + specularColor = float3(0, 0, 0); + normal = float3(0, 0, 1); + shininess = 4; + ambient = float3(0, 0, 0); + emissive = float3(0, 0, 0); + } + + float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) + { + float3 normal_WS = normal; + float diffuse = max(dot(normal_WS, lightDir_WS), 0); + float3 h = normalize(lightDir_WS + viewDir_WS); + float specular = pow(saturate(dot(normal_WS, h)), shininess); + + return (baseColor * diffuse * lightColor) + (specularColor * specular); + } + [mutating] + void transformNormal(float3x3 tangentToWorld) + { + normal = normalize(mul(tangentToWorld, normal)); + } + float3 getNormal() + { + return normal; + } + float3 getBaseColor() + { + return baseColor; + } + float3 evaluateAmbient(float3 viewDir_WS) + { + return ambient; + } + float getAlpha() + { + return alpha; + } + float3 getEmissive() + { + return emissive; + } +}; + +struct CelShading : IBRDF +{ + float3 baseColor; + float alpha; + float3 normal; + float3 emissive; + + __init() + { + baseColor = float3(0, 0, 0); + alpha = 1; + normal = float3(0, 0, 1); + emissive = float3(0, 0, 0); + } + float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) + { + float3 normal_WS = normal; + float nDotL = dot(normal_WS, lightDir_WS); + float diffuse = max(nDotL, 0); + + float3 darkenedBase = baseColor * 0.8; + if(diffuse > 0.5) + { + return baseColor * lightColor; + } + else + { + return darkenedBase * lightColor; + } + } + [mutating] + void transformNormal(float3x3 tangentToWorld) + { + normal = normalize(mul(tangentToWorld, normal)); + } + float3 getNormal() + { + return normal; + } + float3 getBaseColor() + { + return baseColor; + } + float3 evaluateAmbient(float3 viewDir_WS) + { + return float3(0, 0, 0); + } + float getAlpha() + { + return alpha; + } + float3 getEmissive() + { + return emissive; + } +}; + +// https://learnopengl.com/PBR/Theory +struct CookTorrance : IBRDF +{ + float3 baseColor; + float alpha; + float3 normal; + float roughness; + float metallic; + float ambientOcclusion; + float3 emissive; + + __init() + { + baseColor = float3(0, 0, 0); + alpha = 1; + normal = float3(0, 0, 1); + roughness = 0; + metallic = 0; + ambientOcclusion = 1; + emissive = float3(0, 0, 0); + } + + float TrowbridgeReitzGGX(float3 normal, float3 halfway) + { + float a = roughness * roughness; + float a2 = a * a; + float nDotH = max(dot(normal, halfway), 0.0); + float nDotH2 = nDotH * nDotH; + + float nom = a2; + float denom = (nDotH * (a2 - 1.0) + 1.0); + + return nom / (PI * denom * denom); + } + + float SchlickGGX(float nDotV, float k) + { + return nDotV / (nDotV * (1.0 - k) + k); + } + + float Smith(float3 normal, float3 view, float3 light) + { + float k = (roughness + 1); + k = (k * k) / 8; + float nDotV = max(dot(normal, view), 0.0); + float nDotL = max(dot(normal, light), 0.0); + float ggx1 = SchlickGGX(nDotV, k); + float ggx2 = SchlickGGX(nDotL, k); + return ggx1 * ggx2; + } + + float3 FresnelSchlick(float cosTheta, float3 F0) + { + return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); + } + + float3 evaluate(float3 viewDir_WS, float3 lightDir_WS, float3 lightColor) + { + float3 n = normal; + float3 h = normalize(lightDir_WS + viewDir_WS); + + float3 F0 = float3(0.04); + F0 = lerp(F0, baseColor, metallic); + + float NDF = TrowbridgeReitzGGX(n, h); + float G = Smith(n, viewDir_WS, lightDir_WS); + float3 F = FresnelSchlick(max(dot(h, viewDir_WS), 0.0), F0); + + float3 num = NDF * G * F; + float denom = 4.0 * max(dot(n, viewDir_WS), 0.0) * max(dot(n, lightDir_WS), 0.0) + 0.000001; + float3 specular = num / denom; + + float3 k_s = F; + float3 k_d = float3(1.0) - k_s; + + k_d *= 1.0 - metallic; + + float nDotL = max(dot(n, lightDir_WS), 0.0); + + float3 result = (k_d * baseColor / PI + specular) * nDotL * lightColor; + return result; + } + [mutating] + void transformNormal(float3x3 tangentToWorld) + { + normal = normalize(mul(tangentToWorld, normal)); + } + float3 getNormal() + { + return normal; + } + float3 getBaseColor() + { + return baseColor; + } + float3 evaluateAmbient(float3 viewDir_WS) + { + float3 F0 = float3(0.04); + F0 = lerp(F0, baseColor, metallic); + float3 k_s = FresnelSchlick(max(dot(normal, viewDir_WS), 0.0), F0); + float3 k_d = 1 - k_s; + k_d *= 1 - metallic; + float3 irradiance = pLightEnv.irradianceMap.Sample(pLightEnv.irradianceSampler, normal).rgb; + float3 diffuse = irradiance * baseColor; + return (k_d * diffuse) * ambientOcclusion; + } + float getAlpha() + { + return alpha; + } + float3 getEmissive() + { + return emissive; + } +}; + diff --git a/res/shaders/lib/Material.slang b/res/shaders/lib/Material.slang index a3bcd2e..6669f0a 100644 --- a/res/shaders/lib/Material.slang +++ b/res/shaders/lib/Material.slang @@ -1,5 +1,4 @@ import Common; -import BRDF; import MaterialParameter; import Scene; diff --git a/res/shaders/raytracing/ClosestHit.slang b/res/shaders/raytracing/ClosestHit.slang index aa595ce..e0c71d4 100644 --- a/res/shaders/raytracing/ClosestHit.slang +++ b/res/shaders/raytracing/ClosestHit.slang @@ -147,7 +147,7 @@ void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttribu if (rnd.z >= p) return; } - hitValue.light += brdf.getEmissive() * hitValue.emissive + brdf.evaluateAmbient(); + hitValue.light += brdf.getEmissive() * hitValue.emissive + brdf.evaluateAmbient(lightingParams.viewDir_WS); //-- Ideal DIFFUSE reflection //if(bool(useNEE)) { // accrad += nextEventEstimation(accmat, r.d, params.x, params.nl, kt, false, rnd); diff --git a/res/shaders/raytracing/RayTracingData.slang b/res/shaders/raytracing/RayTracingData.slang index 3d5acdc..276b97a 100644 --- a/res/shaders/raytracing/RayTracingData.slang +++ b/res/shaders/raytracing/RayTracingData.slang @@ -1,5 +1,4 @@ import MaterialParameter; -import BRDF; struct RayTracingParams { diff --git a/src/Editor/Asset/EnvironmentLoader.cpp b/src/Editor/Asset/EnvironmentLoader.cpp index 1b90cfe..5127dfb 100644 --- a/src/Editor/Asset/EnvironmentLoader.cpp +++ b/src/Editor/Asset/EnvironmentLoader.cpp @@ -14,6 +14,20 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic .offset = {0, 0}, }, }); + convolutionViewport = graphics->createViewport(nullptr, ViewportCreateInfo{ + .dimensions = + { + .size = {32, 32}, + .offset = {0, 0}, + }, + }); + cubeSampler = graphics->createSampler({ + .magFilter = Gfx::SE_FILTER_LINEAR, + .minFilter = Gfx::SE_FILTER_LINEAR, + .addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeW = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + }); cubeRenderLayout = graphics->createDescriptorLayout("pViewParams"); cubeRenderLayout->addDescriptorBinding(Gfx::DescriptorBinding{ @@ -32,6 +46,10 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic .name = "sampler", .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER, }); + cubeRenderLayout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "cubeMap", + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + }); cubeRenderLayout->create(); cubePipelineLayout = graphics->createPipelineLayout("CubeRenderLayout"); @@ -43,7 +61,8 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic .entryPoints = { {"vertMain", "EnvironmentMapping"}, - {"fragMain", "EnvironmentMapping"}, + {"computeCubemap", "EnvironmentMapping"}, + {"convolveCubemap", "EnvironmentMapping"}, }, .rootSignature = cubePipelineLayout, }); @@ -51,14 +70,7 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic cubeRenderVertex = graphics->createVertexShader({0}); cubeRenderFrag = graphics->createFragmentShader({1}); - - cubeSampler = graphics->createSampler({ - .magFilter = Gfx::SE_FILTER_LINEAR, - .minFilter = Gfx::SE_FILTER_LINEAR, - .addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - .addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - .addressModeW = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - }); + convolutionFrag = graphics->createFragmentShader({2}); } EnvironmentLoader::~EnvironmentLoader() {} @@ -93,12 +105,12 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset }); Matrix4 captureProjection = glm::perspective(glm::radians(90.0f), 1.0f, 0.1f, 10.0f); Matrix4 captureViews[] = { + glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(1.0f, 0.0f, 0.0f), Vector(0.0f, 1.0f, 0.0f)), + glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(-1.0f, 0.0f, 0.0f), Vector(0.0f, 1.0f, 0.0f)), + glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 1.0f, 0.0f), Vector(0.0f, 0.0f, 1.0f)), + glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, -1.0f, 0.0f), Vector(0.0f, 0.0f, -1.0f)), glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, 1.0f), Vector(0.0f, 1.0f, 0.0f)), glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, -1.0f), Vector(0.0f, 1.0f, 0.0f)), - glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, -1.0f, 0.0f), Vector(1.0f, 0.0f, 0.0f)), - glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 1.0f, 0.0f), Vector(1.0f, 0.0f, 0.0f)), - glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(-1.0f, 0.0f, 0.0f), Vector(0.0f, 1.0f, 0.0f)), - glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(1.0f, 0.0f, 0.0f), Vector(0.0f, 1.0f, 0.0f)), }; Gfx::PDescriptorSet set = cubeRenderLayout->allocateDescriptorSet(); set->updateConstants("view", 0, captureViews); @@ -110,9 +122,9 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset .format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT, .width = 1024, .height = 1024, - .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, }); - cubeRenderPass = graphics->createRenderPass( + Gfx::ORenderPass cubeRenderPass = graphics->createRenderPass( Gfx::RenderTargetLayout{ .colorAttachments = {Gfx::RenderTargetAttachment(cubeMap, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, @@ -139,9 +151,57 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset renderCommand->bindPipeline(cubeRenderPipeline); renderCommand->bindDescriptor({set}); renderCommand->setViewport(cubeRenderViewport); - renderCommand->draw(6, 1, 0, 0); + renderCommand->draw(36, 1, 0, 0); graphics->executeCommands(std::move(renderCommand)); graphics->endRenderPass(); + + Gfx::OTextureCube convolutedMap = graphics->createTextureCube(TextureCreateInfo{ + .format = Gfx::SE_FORMAT_R32G32B32A32_SFLOAT, + .width = 32, + .height = 32, + .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + }); + Gfx::ORenderPass convolutionPass = graphics->createRenderPass( + Gfx::RenderTargetLayout{ + .colorAttachments = {Gfx::RenderTargetAttachment(convolutedMap, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, + Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE)}, + }, + {}, + URect{ + .size = {32, 32}, + .offset = {0, 0}, + }, + "EnvironmentRenderPass", {0b111111}, {0b111111}); + convolutionPipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{ + .vertexShader = cubeRenderVertex, + .fragmentShader = convolutionFrag, + .renderPass = convolutionPass, + .pipelineLayout = cubePipelineLayout, + .colorBlend = + { + .attachmentCount = 1, + }, + }); + + set = cubeRenderLayout->allocateDescriptorSet(); + set->updateConstants("view", 0, captureViews); + set->updateConstants("projection", 0, &captureProjection); + set->updateSampler("sampler", 0, cubeSampler); + set->updateTexture("cubeMap", 0, Gfx::PTextureCube(cubeMap)); + set->writeChanges(); + + graphics->beginRenderPass(convolutionPass); + Gfx::ORenderCommand cmd = graphics->createRenderCommand("ConvolutionPass"); + cmd->bindPipeline(convolutionPipeline); + cmd->bindDescriptor({set}); + cmd->setViewport(convolutionViewport); + cmd->draw(36, 1, 0, 0); + graphics->executeCommands(std::move(cmd)); + graphics->endRenderPass(); + + asset->skybox = std::move(cubeMap); + asset->irradianceMap = std::move(convolutedMap); + asset->specularMap = std::move(cubeMap); graphics->waitDeviceIdle(); - asset->diffuseMap = std::move(cubeMap); } diff --git a/src/Editor/Asset/EnvironmentLoader.h b/src/Editor/Asset/EnvironmentLoader.h index 74792d9..968b018 100644 --- a/src/Editor/Asset/EnvironmentLoader.h +++ b/src/Editor/Asset/EnvironmentLoader.h @@ -25,8 +25,10 @@ class EnvironmentLoader { Gfx::ODescriptorLayout cubeRenderLayout; Gfx::OPipelineLayout cubePipelineLayout; Gfx::PGraphicsPipeline cubeRenderPipeline; - Gfx::ORenderPass cubeRenderPass; + Gfx::OFragmentShader convolutionFrag; + Gfx::PGraphicsPipeline convolutionPipeline; Gfx::OViewport cubeRenderViewport; + Gfx::OViewport convolutionViewport; Gfx::OSampler cubeSampler; }; } \ No newline at end of file diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 90e3841..2e425cf 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -100,8 +100,11 @@ int main() { .filePath = sourcePath / "import/textures/skybox.jpg", .type = TextureImportType::TEXTURE_CUBEMAP, }); + //AssetImporter::importEnvironmentMap(EnvironmentImportArgs{ + // .filePath = sourcePath / "import/models/main1_sponza/textures/kloppenheim_05_4k.hdr", + //}); AssetImporter::importEnvironmentMap(EnvironmentImportArgs{ - .filePath = sourcePath / "import/models/main1_sponza/textures/kloppenheim_05_4k.hdr", + .filePath = sourcePath / "import/textures/newport_loft.hdr", }); // AssetImporter::importMesh(MeshImportArgs{ // .filePath = sourcePath / "import/models/ship.fbx", diff --git a/src/Engine/Asset/EnvironmentMapAsset.h b/src/Engine/Asset/EnvironmentMapAsset.h index db847c7..2f3116a 100644 --- a/src/Engine/Asset/EnvironmentMapAsset.h +++ b/src/Engine/Asset/EnvironmentMapAsset.h @@ -11,8 +11,12 @@ class EnvironmentMapAsset : public Asset { virtual ~EnvironmentMapAsset(); virtual void save(ArchiveBuffer& buffer) const override; virtual void load(ArchiveBuffer& buffer) override; + Gfx::PTextureCube getSkybox() const { return skybox; } + Gfx::PTextureCube getIrradianceMap() const { return irradianceMap; } + Gfx::PTextureCube getSpecularMap() const { return specularMap; } private: - Gfx::OTextureCube diffuseMap; + Gfx::OTextureCube skybox; + Gfx::OTextureCube irradianceMap; Gfx::OTextureCube specularMap; friend class EnvironmentLoader; }; diff --git a/src/Engine/Asset/TextureAsset.cpp b/src/Engine/Asset/TextureAsset.cpp index c238606..88118c5 100644 --- a/src/Engine/Asset/TextureAsset.cpp +++ b/src/Engine/Asset/TextureAsset.cpp @@ -45,7 +45,6 @@ void TextureAsset::load(ArchiveBuffer& buffer) { .width = ktxHandle->baseWidth, .height = ktxHandle->baseHeight, .depth = ktxHandle->baseDepth, - .layers = ktxHandle->numFaces, .elements = ktxHandle->numLayers, .useMip = true, .usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT, diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index 24a8c83..b673a91 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -56,7 +56,7 @@ class Graphics { virtual OViewport createViewport(PWindow owner, const ViewportCreateInfo& createInfo) = 0; virtual ORenderPass createRenderPass(RenderTargetLayout layout, Array dependencies, URect renderArea, - std::string name = "", Array viewMasks = {}, Array correlationMasks = {}) = 0; + std::string name = "", Array viewMasks = {0}, Array correlationMasks = {}) = 0; virtual void beginRenderPass(PRenderPass renderPass) = 0; virtual void endRenderPass() = 0; virtual void waitDeviceIdle() = 0; diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index 4889cb8..9eb4bfc 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -49,7 +49,6 @@ struct TextureCreateInfo { uint32 width = 1; uint32 height = 1; uint32 depth = 1; - uint32 layers = 1; uint32 elements = 1; uint32 samples = 1; bool useMip = false; diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 4a47009..1ffd5f9 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -1,6 +1,7 @@ #include "BasePass.h" #include "Actor/CameraActor.h" #include "Asset/AssetRegistry.h" +#include "Asset/EnvironmentMapAsset.h" #include "Component/Camera.h" #include "Component/Mesh.h" #include "Component/WaterTile.h" @@ -78,8 +79,8 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics) }); } skybox = Seele::Component::Skybox{ - .day = AssetRegistry::findTexture("", "skybox")->getTexture().cast(), - .night = AssetRegistry::findTexture("", "skybox")->getTexture().cast(), + .day = scene->getLightEnvironment()->getEnvironmentMap()->getIrradianceMap(), + .night = scene->getLightEnvironment()->getEnvironmentMap()->getIrradianceMap(), .fogColor = Vector(0.1, 0.1, 0.8), .blendFactor = 0, }; diff --git a/src/Engine/Graphics/RenderTarget.h b/src/Engine/Graphics/RenderTarget.h index 2224912..376e87b 100644 --- a/src/Engine/Graphics/RenderTarget.h +++ b/src/Engine/Graphics/RenderTarget.h @@ -108,7 +108,6 @@ class RenderPass { RenderPass(RenderPass&&) = default; RenderPass& operator=(RenderPass&&) = default; const RenderTargetLayout& getLayout() const { return layout; } - void updateColorAttachment(uint32 index, Gfx::PTextureCube attachment) { layout.colorAttachments[index].setTexture(attachment); } protected: RenderTargetLayout layout; diff --git a/src/Engine/Graphics/Vulkan/Framebuffer.cpp b/src/Engine/Graphics/Vulkan/Framebuffer.cpp index 564da50..3ef4275 100644 --- a/src/Engine/Graphics/Vulkan/Framebuffer.cpp +++ b/src/Engine/Graphics/Vulkan/Framebuffer.cpp @@ -16,12 +16,14 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::Render Array attachments; uint32 width = 0; uint32 height = 0; + uint32 layers = 0; for (auto inputAttachment : layout.inputAttachments) { PTextureBase vkInputAttachment = inputAttachment.getTexture().cast(); attachments.add(vkInputAttachment->getView()); description.inputAttachments[description.numInputAttachments++] = vkInputAttachment->getView(); width = std::max(width, vkInputAttachment->getWidth()); height = std::max(height, vkInputAttachment->getHeight()); + layers = std::max(layers, vkInputAttachment->getNumLayers()); } for (auto colorAttachment : layout.colorAttachments) { PTextureBase vkColorAttachment = colorAttachment.getTexture().cast(); @@ -29,6 +31,7 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::Render description.colorAttachments[description.numColorAttachments++] = vkColorAttachment->getView(); width = std::max(width, vkColorAttachment->getWidth()); height = std::max(height, vkColorAttachment->getHeight()); + layers = std::max(layers, vkColorAttachment->getNumLayers()); } for (auto resolveAttachment : layout.resolveAttachments) { PTextureBase vkResolveAttachment = resolveAttachment.getTexture().cast(); @@ -36,6 +39,7 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::Render description.resolveAttachments[description.numResolveAttachments++] = vkResolveAttachment->getView(); width = std::max(width, vkResolveAttachment->getWidth()); height = std::max(height, vkResolveAttachment->getHeight()); + layers = std::max(layers, vkResolveAttachment->getNumLayers()); } if (layout.depthAttachment.getTexture() != nullptr) { PTextureBase vkDepthAttachment = layout.depthAttachment.getTexture().cast(); @@ -43,6 +47,7 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::Render description.depthAttachment = vkDepthAttachment->getView(); width = std::max(width, vkDepthAttachment->getWidth()); height = std::max(height, vkDepthAttachment->getHeight()); + layers = std::max(layers, vkDepthAttachment->getNumLayers()); } if (layout.depthResolveAttachment.getTexture() != nullptr) { PTextureBase vkDepthAttachment = layout.depthResolveAttachment.getTexture().cast(); @@ -50,6 +55,7 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::Render description.depthResolveAttachment = vkDepthAttachment->getView(); width = std::max(width, vkDepthAttachment->getWidth()); height = std::max(height, vkDepthAttachment->getHeight()); + layers = std::max(layers, vkDepthAttachment->getNumLayers()); } VkFramebufferCreateInfo createInfo = { .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, diff --git a/src/Engine/Graphics/Vulkan/RenderPass.cpp b/src/Engine/Graphics/Vulkan/RenderPass.cpp index a9f7c4b..738fa08 100644 --- a/src/Engine/Graphics/Vulkan/RenderPass.cpp +++ b/src/Engine/Graphics/Vulkan/RenderPass.cpp @@ -9,8 +9,8 @@ using namespace Seele; using namespace Seele::Vulkan; -RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Array _dependencies, - URect viewport, std::string name, Array viewMasks, Array correlationMasks) +RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Array _dependencies, URect viewport, + std::string name, Array viewMasks, Array correlationMasks) : Gfx::RenderPass(std::move(_layout), std::move(_dependencies)), graphics(graphics) { renderArea.extent.width = viewport.size.x; renderArea.extent.height = viewport.size.y; @@ -166,6 +166,7 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Arra .pNext = layout.depthResolveAttachment.getTexture() != nullptr ? &depthResolve : nullptr, .flags = 0, .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + .viewMask = viewMasks[0], .inputAttachmentCount = (uint32)inputRefs.size(), .pInputAttachments = inputRefs.data(), .colorAttachmentCount = (uint32)colorRefs.size(), @@ -196,19 +197,9 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Arra .pSubpasses = &subPassDesc, .dependencyCount = (uint32)dep.size(), .pDependencies = dep.data(), + .correlatedViewMaskCount = (uint32)correlationMasks.size(), + .pCorrelatedViewMasks = correlationMasks.data(), }; - VkRenderPassMultiviewCreateInfo multiViewInfo; - if (!viewMasks.empty()) { - multiViewInfo = { - .sType = VK_STRUCTURE_TYPE_RENDER_PASS_MULTIVIEW_CREATE_INFO, - .pNext = nullptr, - .subpassCount = 1, - .pViewMasks = viewMasks.data(), - .correlationMaskCount = (uint32)correlationMasks.size(), - .pCorrelationMasks = correlationMasks.data(), - }; - info.pNext = &multiViewInfo; - } VK_CHECK(vkCreateRenderPass2(graphics->getDevice(), &info, nullptr, &renderPass)); VkDebugUtilsObjectNameInfoEXT nameInfo = { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, diff --git a/src/Engine/Graphics/Vulkan/Texture.cpp b/src/Engine/Graphics/Vulkan/Texture.cpp index 9b69cae..d70f52a 100644 --- a/src/Engine/Graphics/Vulkan/Texture.cpp +++ b/src/Engine/Graphics/Vulkan/Texture.cpp @@ -31,7 +31,7 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format) { TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const TextureCreateInfo& createInfo, VkImage existingImage) : CommandBoundResource(graphics, createInfo.name), image(existingImage), imageView(VK_NULL_HANDLE), allocation(nullptr), owner(createInfo.sourceData.owner), width(createInfo.width), height(createInfo.height), depth(createInfo.depth), - arrayCount(createInfo.elements), layerCount(createInfo.layers), mipLevels(1), samples(createInfo.samples), format(createInfo.format), + layerCount(createInfo.elements), mipLevels(1), samples(createInfo.samples), format(createInfo.format), usage(createInfo.usage), layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED), aspect(getAspectFromFormat(createInfo.format)), ownsImage(false) { if (createInfo.useMip) { mipLevels = static_cast(std::floor(std::log2(std::max(width, height)))) + 1; @@ -55,7 +55,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: type = VK_IMAGE_TYPE_2D; flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; - layerCount = 6 * arrayCount; + layerCount = 6 * layerCount; break; default: break; @@ -76,7 +76,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const .depth = depth, }, .mipLevels = mipLevels, - .arrayLayers = arrayCount * layerCount, + .arrayLayers = layerCount, .samples = (VkSampleCountFlagBits)samples, .tiling = VK_IMAGE_TILING_OPTIMAL, .usage = usage, @@ -129,7 +129,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .mipLevel = 0, .baseArrayLayer = 0, - .layerCount = arrayCount * layerCount, + .layerCount = layerCount, }, .imageOffset = { @@ -163,7 +163,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, const { .aspectMask = aspect, .levelCount = mipLevels, - .layerCount = layerCount * arrayCount, + .layerCount = layerCount, }, }; @@ -195,7 +195,7 @@ void TextureHandle::pipelineBarrier(VkAccessFlags srcAccess, VkPipelineStageFlag .baseMipLevel = 0, .levelCount = mipLevels, .baseArrayLayer = 0, - .layerCount = layerCount * arrayCount, + .layerCount = layerCount, }, }; PCommand command = graphics->getQueueCommands(owner)->getCommands(); @@ -223,7 +223,7 @@ void TextureHandle::transferOwnership(Gfx::QueueType newOwner) { .baseMipLevel = 0, .levelCount = mipLevels, .baseArrayLayer = 0, - .layerCount = arrayCount, + .layerCount = layerCount, }, }; PCommandPool sourcePool = graphics->getQueueCommands(owner); diff --git a/src/Engine/Graphics/Vulkan/Texture.h b/src/Engine/Graphics/Vulkan/Texture.h index 8104c72..acd998b 100644 --- a/src/Engine/Graphics/Vulkan/Texture.h +++ b/src/Engine/Graphics/Vulkan/Texture.h @@ -25,7 +25,6 @@ class TextureHandle : public CommandBoundResource { uint32 width; uint32 height; uint32 depth; - uint32 arrayCount; uint32 layerCount; uint32 mipLevels; uint32 samples; @@ -48,6 +47,7 @@ class TextureBase { uint32 getWidth() const { return handle->width; } uint32 getHeight() const { return handle->height; } uint32 getDepth() const { return handle->depth; } + uint32 getNumLayers() const { return handle->layerCount; } PTextureHandle getHandle() const { return handle; } VkImage getImage() const { return handle->image; }; VkImageView getView() const { return handle->imageView; }; diff --git a/src/Engine/Graphics/Vulkan/Window.cpp b/src/Engine/Graphics/Vulkan/Window.cpp index a5f0e18..300ecbd 100644 --- a/src/Engine/Graphics/Vulkan/Window.cpp +++ b/src/Engine/Graphics/Vulkan/Window.cpp @@ -276,7 +276,6 @@ void Window::createSwapChain() { .width = extent.width, .height = extent.height, .depth = 1, - .layers = 1, .elements = 1, .samples = 1, .usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_TRANSFER_DST_BIT, diff --git a/src/Engine/Graphics/Window.cpp b/src/Engine/Graphics/Window.cpp index 34da7a2..b33cc6d 100644 --- a/src/Engine/Graphics/Window.cpp +++ b/src/Engine/Graphics/Window.cpp @@ -9,7 +9,12 @@ Window::~Window() {} Viewport::Viewport(PWindow owner, const ViewportCreateInfo& viewportInfo) : sizeX(viewportInfo.dimensions.size.x), sizeY(viewportInfo.dimensions.size.y), offsetX(viewportInfo.dimensions.offset.x), - offsetY(viewportInfo.dimensions.offset.y), fieldOfView(viewportInfo.fieldOfView), owner(owner) {} + offsetY(viewportInfo.dimensions.offset.y), fieldOfView(viewportInfo.fieldOfView), owner(owner) { + if (owner != nullptr) { + sizeX = std::min(owner->getFramebufferWidth(), sizeX); + sizeY = std::min(owner->getFramebufferHeight(), sizeY); + } +} Viewport::~Viewport() {} diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index f317628..9001d87 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -158,8 +158,8 @@ void Material::load(ArchiveBuffer& buffer) { void Material::compile() { std::ofstream codeStream("./shaders/generated/" + materialName + ".slang"); - codeStream << "import BRDF;\n"; codeStream << "import MaterialParameter;\n"; + codeStream << "import LightEnv;\n"; codeStream << "import Material;\n"; codeStream << "struct Material{\n"; codeStream << "\ttypedef " << brdf.profile << " BRDF;\n"; diff --git a/src/Engine/Scene/LightEnvironment.cpp b/src/Engine/Scene/LightEnvironment.cpp index 854f141..fbbd1a6 100644 --- a/src/Engine/Scene/LightEnvironment.cpp +++ b/src/Engine/Scene/LightEnvironment.cpp @@ -1,9 +1,12 @@ #include "LightEnvironment.h" +#include "Asset/EnvironmentMapAsset.h" #include "Graphics/Graphics.h" +#include "Asset/AssetRegistry.h" using namespace Seele; -LightEnvironment::LightEnvironment(Gfx::PGraphics graphics) : graphics(graphics) { +LightEnvironment::LightEnvironment(Gfx::PGraphics graphics) + : graphics(graphics), environment(AssetRegistry::findEnvironmentMap("", "newport_loft")) { layout = graphics->createDescriptorLayout("pLightEnv"); layout->addDescriptorBinding(Gfx::DescriptorBinding{ .name = "directionalLights", @@ -21,6 +24,10 @@ LightEnvironment::LightEnvironment(Gfx::PGraphics graphics) : graphics(graphics) .name = "numPointLights", .uniformLength = sizeof(uint32), }); + layout->addDescriptorBinding(Gfx::DescriptorBinding{ + .name = "irradianceMap", + .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, + }); layout->create(); directionalLights = graphics->createShaderBuffer(ShaderBufferCreateInfo{ @@ -29,6 +36,13 @@ LightEnvironment::LightEnvironment(Gfx::PGraphics graphics) : graphics(graphics) pointLights = graphics->createShaderBuffer(ShaderBufferCreateInfo{ .name = "PointLights", }); + environmentSampler = graphics->createSampler({ + .magFilter = Gfx::SE_FILTER_LINEAR, + .minFilter = Gfx::SE_FILTER_LINEAR, + .addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeW = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + }); } LightEnvironment::~LightEnvironment() {} @@ -63,6 +77,7 @@ void LightEnvironment::commit() { set->updateBuffer("pointLights", 0, pointLights); set->updateConstants("numDirectionalLights", 0, &numDirectionalLights); set->updateBuffer("directionalLights", 0, directionalLights); + set->updateTexture("irradianceMap", 0, environment->getIrradianceMap()); set->writeChanges(); } diff --git a/src/Engine/Scene/LightEnvironment.h b/src/Engine/Scene/LightEnvironment.h index ac889b8..1cf2435 100644 --- a/src/Engine/Scene/LightEnvironment.h +++ b/src/Engine/Scene/LightEnvironment.h @@ -4,8 +4,8 @@ #include "Graphics/Buffer.h" #include "Graphics/Descriptor.h" - namespace Seele { +DECLARE_REF(EnvironmentMapAsset) class LightEnvironment { public: LightEnvironment(Gfx::PGraphics graphics); @@ -16,12 +16,15 @@ class LightEnvironment { void commit(); const Gfx::PDescriptorLayout getDescriptorLayout() const; Gfx::PDescriptorSet getDescriptorSet(); + PEnvironmentMapAsset getEnvironmentMap() { return environment; } private: Gfx::OShaderBuffer directionalLights; Gfx::OShaderBuffer pointLights; Array dirs; Array points; + PEnvironmentMapAsset environment; + Gfx::OSampler environmentSampler; Gfx::ODescriptorLayout layout; Gfx::PDescriptorSet set; Gfx::PGraphics graphics; diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index 9fe59be..7f646f3 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -1,6 +1,5 @@ #include "Scene.h" #include "Actor/PointLightActor.h" -#include "Asset/AssetRegistry.h" #include "Asset/MaterialAsset.h" #include "Asset/TextureAsset.h" #include "Component/DirectionalLight.h" @@ -13,7 +12,8 @@ using namespace Seele; -Scene::Scene(Gfx::PGraphics graphics) : graphics(graphics), lightEnv(new LightEnvironment(graphics)), physics(registry) {} +Scene::Scene(Gfx::PGraphics graphics) + : graphics(graphics), lightEnv(new LightEnvironment(graphics)), physics(registry) {} Scene::~Scene() {} diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index 59d7238..e68b025 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -1,8 +1,8 @@ #pragma once +#include "MinimalEngine.h" #include "Component/Skybox.h" #include "Graphics/Graphics.h" #include "LightEnvironment.h" -#include "MinimalEngine.h" #include "Physics/PhysicsSystem.h" #include #include