updated the deferred pipeline to use PBR, and added skybox to its workflow

This commit is contained in:
Anselme 2017-08-15 17:18:34 +02:00
parent 1f22f90342
commit 8c987af313
23 changed files with 665 additions and 570 deletions

248
CMakeLists.txt.user.6bc6d81 Normal file
View File

@ -0,0 +1,248 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.2.1, 2017-02-23T12:15:05. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{6bc6d814-5082-4cc7-a3fd-c0503e9952d9}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="int">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap"/>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.8.0 MinGW 32bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.8.0 MinGW 32bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.58.win32_mingw53_kit</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<valuelist type="QVariantList" key="CMake.Configuration">
<value type="QString">CMAKE_BUILD_TYPE:STRING=Debug</value>
<value type="QString">CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}</value>
<value type="QString">CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}</value>
<value type="QString">QT_QMAKE_EXECUTABLE:STRING=C:/Qt/5.7/mingw53_32/bin/qmake.exe</value>
</valuelist>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/Anselme/git/SparrowRenderer/build-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<valuelist type="QVariantList" key="CMake.Configuration">
<value type="QString">CMAKE_BUILD_TYPE:STRING=Release</value>
<value type="QString">CMAKE_CXX_COMPILER:STRING=%{Compiler:Executable:Cxx}</value>
<value type="QString">CMAKE_C_COMPILER:STRING=%{Compiler:Executable:C}</value>
<value type="QString">QT_QMAKE_EXECUTABLE:STRING=C:/Qt/5.7/mingw53_32/bin/qmake.exe</value>
</valuelist>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/Anselme/git/SparrowRenderer/build-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">all</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="QString" key="CMakeProjectManager.MakeStep.AdditionalArguments"></value>
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
<value type="QString">clean</value>
</valuelist>
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
<value type="int">0</value>
<value type="int">1</value>
<value type="int">2</value>
<value type="int">3</value>
<value type="int">4</value>
<value type="int">5</value>
<value type="int">6</value>
<value type="int">7</value>
<value type="int">8</value>
<value type="int">9</value>
<value type="int">10</value>
<value type="int">11</value>
<value type="int">12</value>
<value type="int">13</value>
<value type="int">14</value>
</valuelist>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguation.Title">SparrowResource</value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.Arguments"></value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory"></value>
<value type="QString" key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory.default">C:/Users/Anselme/git/SparrowRenderer/build-Release</value>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">SparrowResource</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.SparrowResource</value>
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="int">1</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">18</value>
</data>
<data>
<variable>Version</variable>
<value type="int">18</value>
</data>
</qtcreator>

View File

@ -1,34 +1,38 @@
// - Position in view space // - Position in view space
layout (location = 0) out vec4 outPosition; layout (location = 0) out vec4 outPosition;
// - Color + objectId buffer // - Albedo + Roughness
layout (location = 1) out vec4 outColor; layout (location = 1) out vec4 outAlbedo;
// - Normal buffer // - Normal buffer
layout (location = 2) out vec3 outNormal; layout (location = 2) out vec3 outNormal;
// - Specular color + Specular exponent buffer // - Emission + Metallic
layout (location = 3) out vec4 outSpecular; layout (location = 3) out vec4 outEmission;
uniform float materialNs;
// variables used for picking
uniform int object_identifier;
#ifdef INSTANCED
flat in int instanceId;
#endif
#ifdef ALPHA_MASK #ifdef ALPHA_MASK
uniform sampler2D alphaMask; uniform sampler2D alphaMask;
#endif #endif
#ifdef DIFFUSE_TEXTURE #ifdef ALBEDO_TEXTURE
uniform sampler2D diffuseTexture; uniform sampler2D albedoTexture;
#else #else
uniform vec3 materialKd; uniform vec3 albedo;
#endif #endif
#ifdef SPECULAR_TEXTURE #ifdef EMISSION_TEXTURE
uniform sampler2D specularTexture; uniform sampler2D emissionTexture;
#else #else
uniform vec3 materialKs; uniform vec3 emission;
#endif
#ifdef ROUGHNESS_TEXTURE
uniform sampler2D roughnessTexture;
#else
uniform float roughness;
#endif
#ifdef METALLIC_TEXTURE
uniform sampler2D metallicTexture;
#else
uniform float metallic;
#endif #endif
in vec4 posInView; in vec4 posInView;
@ -50,9 +54,11 @@ in vec2 varTexCoord;
void main() void main()
{ {
#ifdef WIREFRAME #ifdef WIREFRAME
outColor.rgb = varColor; outAlbedo.rgb = vec3(0., 0., 0.); // black
outNormal = vec3(0., 0., 1.); outAlbedo.a = 1.; // full roughness
outSpecular = vec4(0., 0., 0., 1.); outEmission.rgb = varColor;
outEmission.a = 0.; // not metallic
outNormal = vec3(0., 0., 1.); // oriented towards the eye
#else #else
#ifdef ALPHA_MASK #ifdef ALPHA_MASK
@ -74,27 +80,31 @@ void main()
outNormal = normalize(varNormal); outNormal = normalize(varNormal);
#endif #endif
#ifdef DIFFUSE_TEXTURE #ifdef ALBEDO_TEXTURE
outColor.rgb = texture(diffuseTexture, varTexCoord).rgb; outAlbedo.rgb = texture(albedoTexture, varTexCoord).rgb;
#else #else
outColor.rgb = materialKd; outAlbedo.rgb = albedo;
#endif #endif
#ifdef SPECULAR_TEXTURE #ifdef ROUGHNESS_TEXTURE
outSpecular.rgb = texture(specularTexture, varTexCoord).rgb; outAlbedo.a = texture(roughnessTexture, varTexCoord).r;
#else #else
outSpecular.rgb = materialKs; outAlbedo.a = roughness;
#endif #endif
outSpecular.w = float(materialNs)/255; #ifdef EMISSION_TEXTURE
outEmission.rgb = texture(emissionTexture, varTexCoord).rgb;
#else
outEmission.rgb = emission;
#endif
#ifdef METALLIC_TEXTURE
outEmission.a = texture(metallicTexture, varTexCoord).r;
#else
outEmission.a = metallic;
#endif
#endif // WIREFRAME #endif // WIREFRAME
#ifdef INSTANCED
outColor.a = float(object_identifier+instanceId)/255;
#else
outColor.a = float(object_identifier)/255;
#endif
outPosition = posInView; outPosition = posInView;
} }

View File

@ -26,8 +26,6 @@ layout(location = 4)in vec3 inBinormal;
#ifdef INSTANCED #ifdef INSTANCED
layout(location = 5)in vec3 inInstanceOffset; layout(location = 5)in vec3 inInstanceOffset;
flat out int instanceId;
#endif #endif
void main(void) { void main(void) {
@ -48,7 +46,6 @@ void main(void) {
// computing positions // computing positions
#ifdef INSTANCED #ifdef INSTANCED
instanceId = gl_InstanceID;
vec4 pos = vec4(inPosition + inInstanceOffset, 1.0); vec4 pos = vec4(inPosition + inInstanceOffset, 1.0);
#else #else
vec4 pos = vec4(inPosition, 1.0); vec4 pos = vec4(inPosition, 1.0);

View File

@ -5,9 +5,9 @@ in vec2 texCoord;
#endif #endif
#ifdef DIFFUSE_TEXTURE #ifdef DIFFUSE_TEXTURE
uniform sampler2D diffuseTexture; uniform sampler2D albedoTexture;
#else #else
uniform vec3 materialKd; uniform vec3 albedo;
#endif #endif
#ifdef ALPHA_MASK #ifdef ALPHA_MASK
@ -25,9 +25,9 @@ layout(location = 0)out vec4 outColor;
void main(void) void main(void)
{ {
#ifdef DIFFUSE_TEXTURE #ifdef DIFFUSE_TEXTURE
vec3 color = texture(diffuseTexture, texCoord).rgb; vec3 color = texture(albedoTexture, texCoord).rgb;
#else #else
vec3 color = materialKd; vec3 color = albedo;
#endif #endif
#ifdef ALPHA_MASK #ifdef ALPHA_MASK

View File

@ -2,18 +2,24 @@
// - Position in view space // - Position in view space
uniform sampler2DRect positionBuffer; uniform sampler2DRect positionBuffer;
// - Color + objectId buffer // - Albedo + Roughness
uniform sampler2DRect colorBuffer; uniform sampler2DRect albedoBuffer;
// - Normal buffer // - Normal buffer
uniform sampler2DRect normalBuffer; uniform sampler2DRect normalBuffer;
// - Specular color + Specular exponent buffer // - Emission + Metallic
uniform sampler2DRect specularBuffer; uniform sampler2DRect emissionBuffer;
// - depth buffer // - depth buffer
uniform sampler2DRect depthBuffer; uniform sampler2DRect depthBuffer;
// LIGHT ATTRIBUTES // LIGHT ATTRIBUTES
#ifdef AMBIENT_LIGHT
uniform samplerCube ambientMap;
uniform samplerCube reflectMap;
uniform sampler2D brdfLUT;
uniform mat3 inverseViewMatrix;
#else
uniform vec3 lightColor; uniform vec3 lightColor;
#endif
#ifdef SHADOWMAP #ifdef SHADOWMAP
#ifdef POINT_LIGHT #ifdef POINT_LIGHT
@ -47,61 +53,109 @@ uniform mat4 inverseProjectionMatrix;
layout(location = 0)out vec4 outColor; layout(location = 0)out vec4 outColor;
// CONSTANTS
const float PI = 3.14159265359;
const float MAX_REFLECTION_LOD = 4.0;
// FUNCTIONS // FUNCTIONS
const float CELL_SHADING = 0.3333; #ifdef AMBIENT_LIGHT
vec3 GGX(
in vec3 albedoColor,
in float metallic,
in float roughness,
in vec3 N,
in vec3 V)
{
float NdotV = max(dot(N, V), 0.0);
vec3 R = reflect(-V, N);
vec3 albedo = pow(albedoColor, vec3(2.2));
vec3 F0 = mix(vec3(0.04), albedo, metallic);
vec3 phongLighting(in vec3 kd, in vec3 ks, in float ns, in vec3 color, in vec3 normal, in vec3 lightDir, in vec3 halfVec, in vec3 viewDir){ // ambient lighting (we now use IBL as the ambient term) (fresnelSchlickRoughness function)
float diffuseComponent = max(dot(normal, lightDir), 0); vec3 F = F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - NdotV, 5.0);
float specularComponent = max(dot(halfVec, normal), 0);
return color*diffuseComponent*(kd+ks*pow(specularComponent, ns)); vec3 kD = 1.0 - F;
kD *= 1.0 - metallic;
vec3 irradiance = texture(ambientMap, inverseViewMatrix * N).rgb;
vec3 diffuse = irradiance * albedo;
// sample both the pre-filter map and the BRDF lut and combine them together as per the Split-Sum approximation to get the IBL specular part.
vec3 prefilteredColor = textureLod(reflectMap, inverseViewMatrix * R, roughness * MAX_REFLECTION_LOD).rgb;
vec2 brdf2 = texture(brdfLUT, vec2(NdotV, roughness)).rg;
vec3 specular = prefilteredColor * (F * brdf2.x + brdf2.y);
// combining light
return kD * diffuse + specular;
}
#else
float DistributionGGX(vec3 N, vec3 H, float roughness)
{
float a = roughness*roughness;
float a2 = a*a;
float NdotH = max(dot(N, H), 0.0);
float denom = (NdotH * NdotH * (a2 - 1.0) + 1.0);
denom = PI * denom * denom;
return a2 / denom;
} }
vec3 CookTorranceSpecularHighlight(in vec3 ks, in float ns, in vec3 normal, in vec3 lightDir, in vec3 halfVec, in vec3 viewDir){ float GeometrySchlickGGX(float cosAlpha, float roughness)
float HN = dot(halfVec, normal); {
float VN = dot(viewDir, normal); float r = (roughness + 1.0);
float VH = dot(viewDir, halfVec); float k = (r*r) / 8.0;
float LN = dot(lightDir, normal); return cosAlpha / (cosAlpha * (1.0 - k) + k);
HN = max(HN, 0);
VN = max(VN, 0);
LN = max(LN, 0);
// GGX normal distribution :
float roughness = 2/(ns+2);
float denom = mix(1, roughness, HN*HN);
float D = roughness/(3.1416*denom*denom);
//D = pow(HN, ns);
// Fresnel term with Schlick's approximation
vec3 F = mix(ks, vec3(1), pow(1 - VH, 5));
VH = max(VH, 0);
// Geometric attenuation
float G = min(1, min(2*HN*VN/VH, 2*HN*LN/VH));
return D * F * G;
} }
vec3 testLighting(in vec3 kd, in vec3 ks, in float ns, in vec3 color, in vec3 normal, in vec3 lightDir, in vec3 halfVec, in vec3 viewDir){ vec3 GGX(
float diffuseComponent = max(dot(normal, lightDir), 0); in vec3 albedoColor,
return color*diffuseComponent*(kd+ks*CookTorranceSpecularHighlight(ks, ns, normal, lightDir, halfVec, viewDir)); in float metallic,
in float roughness,
in vec3 radiance,
in vec3 N,
in vec3 L,
in vec3 H,
in vec3 V)
{
vec3 albedo = pow(albedoColor, vec3(2.2));
vec3 F0 = mix(vec3(0.04), albedo, metallic);
float NdotL = max(dot(N, L), 0.0);
float NdotV = max(dot(N, V), 0.0);
// Cook-Torrance BRDF
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySchlickGGX(NdotV, roughness) * GeometrySchlickGGX(NdotL, roughness);
vec3 F = F0 + (1.0 - F0) * pow(1.0 - max(dot(H, V), 0.0), 5.0);
vec3 nominator = NDF * G * F;
float denominator = 4 * NdotV * NdotL + 0.001; // 0.001 to prevent divide by zero.
vec3 brdf = nominator / denominator;
vec3 kD = 1.0 - F;
kD *= 1.0 - metallic;
return (kD * albedo / PI + brdf) * radiance * NdotL;
} }
#endif
// MAIN PROGRAM // MAIN PROGRAM
void main(void) { void main(void) {
// get fragment information from the G-Buffer
ivec2 texCoord = ivec2(gl_FragCoord.xy); ivec2 texCoord = ivec2(gl_FragCoord.xy);
vec3 normal = texelFetch(normalBuffer, texCoord).xyz; vec3 normal = texelFetch(normalBuffer, texCoord).xyz;
vec4 diffuseTexel = texelFetch(colorBuffer, texCoord); vec4 albedoTexel = texelFetch(albedoBuffer, texCoord);
vec3 diffuse = diffuseTexel.rgb; vec3 albedo = albedoTexel.rgb;
vec4 specularTexel = texelFetch(specularBuffer, texCoord); float roughness = albedoTexel.a;
vec3 specular = specularTexel.rgb; vec4 emissionTexel = texelFetch(emissionBuffer, texCoord);
float shininess = specularTexel.w*255; vec3 emission = emissionTexel.rgb;
float metallic = emissionTexel.a;
vec4 fragPos = texelFetch(positionBuffer, texCoord); vec4 fragPos = texelFetch(positionBuffer, texCoord);
float depth = texelFetch(depthBuffer, texCoord).r; float depth = texelFetch(depthBuffer, texCoord).r;
// compute shadow
#ifdef SHADOWMAP #ifdef SHADOWMAP
#ifdef POINT_LIGHT #ifdef POINT_LIGHT
float shadow = 1; float shadow = 1;
@ -128,12 +182,12 @@ void main(void) {
dirLight = normalize(dirLight); dirLight = normalize(dirLight);
#endif #endif
#ifdef AMBIENT_LIGHT
outColor = vec4(diffuse*lightColor, 1);
#else
vec3 viewDir = normalize(-fragPos.xyz); vec3 viewDir = normalize(-fragPos.xyz);
#ifdef AMBIENT_LIGHT
outColor = vec4(emission + GGX(albedo, metallic, roughness, normal, viewDir), 1);
#else
vec3 halfVec = normalize(viewDir + dirLight); vec3 halfVec = normalize(viewDir + dirLight);
vec3 light = testLighting(diffuse, specular, shininess, lightColor, normal, dirLight, halfVec, viewDir); vec3 light = GGX(albedo, metallic, roughness, lightColor, normal, dirLight, halfVec, viewDir);
outColor = vec4(mix(vec3(0.0), light*shadow, att*att), 1); outColor = vec4(mix(vec3(0.0), light*shadow, att*att), 1);
#endif #endif
} }

View File

@ -13,5 +13,12 @@ layout(location = 0)out vec4 outColor;
void main(void) { void main(void) {
ivec2 texCoord = ivec2(gl_FragCoord.xy); ivec2 texCoord = ivec2(gl_FragCoord.xy);
vec3 color = texelFetch(lightBuffer, texCoord).xyz; vec3 color = texelFetch(lightBuffer, texCoord).xyz;
// HDR tonemapping
color = color / (color + vec3(1.0));
// gamma correct
color = pow(color, vec3(1.0/2.2));
outColor = vec4(color, 1.0); outColor = vec4(color, 1.0);
} }

View File

@ -6,8 +6,9 @@
#include "shader.h" #include "shader.h"
#include <glm/ext.hpp> #include <glm/ext.hpp>
#include "shadersource.h" #include "shadersource.h"
#include "phongmaterial.h" #include "pbrmaterial.h"
#include "camera.h" #include "camera.h"
#include "skybox.h"
#include "guimesh.h" #include "guimesh.h"
#include <resource.h> #include <resource.h>
#include <algorithm> #include <algorithm>
@ -24,10 +25,10 @@ GBuffer::GBuffer(int width, int height) : FrameBuffer()
tex->setUnit(POSITION); tex->setUnit(POSITION);
addTexture(tex, GL_COLOR_ATTACHMENT0); addTexture(tex, GL_COLOR_ATTACHMENT0);
// - Color + objectId buffer // - Albedo + Roughness
tex = new Texture(GL_RGBA, GL_RGBA, width, height, GL_UNSIGNED_BYTE, GL_TEXTURE_RECTANGLE); tex = new Texture(GL_RGBA, GL_RGBA, width, height, GL_UNSIGNED_BYTE, GL_TEXTURE_RECTANGLE);
tex->setFiltering(GL_NEAREST); tex->setFiltering(GL_NEAREST);
tex->setUnit(DIFFUSE); tex->setUnit(ALBEDO);
addTexture(tex, GL_COLOR_ATTACHMENT1); addTexture(tex, GL_COLOR_ATTACHMENT1);
// - Normal buffer // - Normal buffer
@ -36,10 +37,10 @@ GBuffer::GBuffer(int width, int height) : FrameBuffer()
tex->setUnit(NORMAL); tex->setUnit(NORMAL);
addTexture(tex, GL_COLOR_ATTACHMENT2); addTexture(tex, GL_COLOR_ATTACHMENT2);
// - Specular color + Specular exponent buffer // - Emission + Metallic
tex = new Texture(GL_RGBA, GL_RGBA, width, height, GL_UNSIGNED_BYTE, GL_TEXTURE_RECTANGLE); tex = new Texture(GL_RGBA, GL_RGBA, width, height, GL_UNSIGNED_BYTE, GL_TEXTURE_RECTANGLE);
tex->setFiltering(GL_NEAREST); tex->setFiltering(GL_NEAREST);
tex->setUnit(SPECULAR); tex->setUnit(EMISSION);
addTexture(tex, GL_COLOR_ATTACHMENT3); addTexture(tex, GL_COLOR_ATTACHMENT3);
// - depth buffer // - depth buffer
@ -74,12 +75,13 @@ LightingBuffer::LightingBuffer(int width, int height) : FrameBuffer()
} }
DeferredPipeline::DeferredPipeline() : DeferredPipeline::DeferredPipeline() :
m_camera(NULL), m_camera(nullptr),
m_skybox(nullptr),
m_width(512), m_width(512),
m_height(512), m_height(512),
m_gBuffer(NULL), m_gBuffer(nullptr),
m_lightingBuffer(NULL), m_lightingBuffer(nullptr),
m_renderTarget(NULL) m_renderTarget(nullptr)
{ {
Resource::ResourceMap shaderMap; Resource::ResourceMap shaderMap;
Resource::getResourcePack_shaders(shaderMap); Resource::getResourcePack_shaders(shaderMap);
@ -120,7 +122,6 @@ void DeferredPipeline::renderGL(Scene *scene)
glClearDepth(1.0f); glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// loop on geometry // loop on geometry
unsigned int id = 2;
for(SceneIterator<GeometryNode*>* geometryIt = scene->getGeometry(); for(SceneIterator<GeometryNode*>* geometryIt = scene->getGeometry();
geometryIt->isValid(); geometryIt->next()) geometryIt->isValid(); geometryIt->next())
{ {
@ -138,13 +139,7 @@ void DeferredPipeline::renderGL(Scene *scene)
continue; continue;
} }
shader->bind(); shader->bind();
shader->bindUnsignedInteger(shader->getLocation("object_identifier"), id);
if(node->mesh->instances_offsets.empty())
++id;
else
id += node->mesh->instances_offsets.size();
glm::mat4 modelViewMatrix = m_camera->getViewMatrix() * node->modelMatrix; glm::mat4 modelViewMatrix = m_camera->getViewMatrix() * node->modelMatrix;
glm::mat4 normalMatrix = glm::transpose(glm::inverse(modelViewMatrix)); glm::mat4 normalMatrix = glm::transpose(glm::inverse(modelViewMatrix));
shader->bindMat4(shader->getLocation("projectionMatrix"), m_camera->getProjectionMatrix()); shader->bindMat4(shader->getLocation("projectionMatrix"), m_camera->getProjectionMatrix());
@ -156,6 +151,9 @@ void DeferredPipeline::renderGL(Scene *scene)
// LIGHTING PASS // LIGHTING PASS
m_lightingBuffer->bindFBO(); m_lightingBuffer->bindFBO();
if(m_skybox != nullptr)
m_skybox->renderGL(m_camera);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE); glBlendFunc(GL_ONE, GL_ONE);
@ -175,9 +173,9 @@ void DeferredPipeline::renderGL(Scene *scene)
// bind GBuffer // bind GBuffer
shader->bindInteger(shader->getLocation("positionBuffer"), GBuffer::POSITION); shader->bindInteger(shader->getLocation("positionBuffer"), GBuffer::POSITION);
shader->bindInteger(shader->getLocation("colorBuffer"), GBuffer::DIFFUSE); shader->bindInteger(shader->getLocation("albedoBuffer"), GBuffer::ALBEDO);
shader->bindInteger(shader->getLocation("normalBuffer"), GBuffer::NORMAL); shader->bindInteger(shader->getLocation("normalBuffer"), GBuffer::NORMAL);
shader->bindInteger(shader->getLocation("specularBuffer"), GBuffer::SPECULAR); shader->bindInteger(shader->getLocation("emissionBuffer"), GBuffer::EMISSION);
shader->bindInteger(shader->getLocation("depthBuffer"), GBuffer::DEPTH); shader->bindInteger(shader->getLocation("depthBuffer"), GBuffer::DEPTH);
// bind light // bind light
@ -219,7 +217,19 @@ void DeferredPipeline::renderGL(Scene *scene)
} }
// IMGUI PASS // IMGUI PASS
gui.drawGL(); m_guiMesh->drawGL();
}
void DeferredPipeline::setSkybox(Texture* texture)
{
if(m_skybox != nullptr)
delete m_skybox;
m_skybox = nullptr;
if(texture != nullptr)
{
m_skybox = new Skybox(texture);
m_skybox->resizeGL(m_width, m_height);
}
} }
void DeferredPipeline::resizeGL(int w, int h) void DeferredPipeline::resizeGL(int w, int h)
@ -228,6 +238,9 @@ void DeferredPipeline::resizeGL(int w, int h)
m_width = w; m_width = w;
m_height = h; m_height = h;
if(m_skybox != nullptr)
m_skybox->resizeGL(w, h);
// rebuilding FrameBuffers // rebuilding FrameBuffers
if(m_gBuffer != NULL) if(m_gBuffer != NULL)
{ {

View File

@ -8,12 +8,13 @@
class Shader; class Shader;
class Camera; class Camera;
class Skybox;
class GuiMesh; class GuiMesh;
class GBuffer : public FrameBuffer class GBuffer : public FrameBuffer
{ {
public: public:
enum Buffers { POSITION, DIFFUSE, NORMAL, SPECULAR, DEPTH, NB_BUFFERS }; enum Buffers { POSITION, ALBEDO, NORMAL, EMISSION, DEPTH, NB_BUFFERS };
GBuffer(int width, int height); GBuffer(int width, int height);
void bindTextures(); void bindTextures();
void unbindTextures(); void unbindTextures();
@ -28,7 +29,9 @@ public:
class DeferredPipeline : public Pipeline class DeferredPipeline : public Pipeline
{ {
Camera *m_camera; Camera *m_camera;
Skybox* m_skybox;
int m_width; int m_width;
int m_height; int m_height;
@ -60,6 +63,7 @@ public:
void setCamera(Camera *camera) { m_camera = camera; } void setCamera(Camera *camera) { m_camera = camera; }
void setSources(ShaderSource *gBufferSource, ShaderSource *lightingSource, ShaderSource *guiSource, Shader *postEffectsShader); void setSources(ShaderSource *gBufferSource, ShaderSource *lightingSource, ShaderSource *guiSource, Shader *postEffectsShader);
void setRenderTarget(const FrameBuffer *fbo) { m_renderTarget = fbo; } void setRenderTarget(const FrameBuffer *fbo) { m_renderTarget = fbo; }
void setSkybox(Texture* texture);
void refreshScene(Scene *scene); void refreshScene(Scene *scene);
virtual void renderGL(Scene *scene); virtual void renderGL(Scene *scene);

View File

@ -3,7 +3,7 @@
#include "mesh.h" #include "mesh.h"
#include "shader.h" #include "shader.h"
#include "light.h" #include "light.h"
#include "phongmaterial.h" #include "pbrmaterial.h"
#include "texture.h" #include "texture.h"
#include "camera.h" #include "camera.h"
#include <glm/ext.hpp> #include <glm/ext.hpp>

View File

@ -4,7 +4,7 @@
#include "scene.h" #include "scene.h"
#include "shader.h" #include "shader.h"
#include "shadersource.h" #include "shadersource.h"
#include "phongmaterial.h" #include "pbrmaterial.h"
#include "mesh.h" #include "mesh.h"
#include "camera.h" #include "camera.h"
#include <resource.h> #include <resource.h>
@ -28,9 +28,23 @@ const glm::mat4 Light::biasMatrix(
0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0); 0.5, 0.5, 0.5, 1.0);
Texture* AmbientLight::brdfLUT = nullptr;
void AmbientLight::bindAttributes(Shader *shader, Camera *camera) void AmbientLight::bindAttributes(Shader *shader, Camera *camera)
{ {
shader->bindVec3(shader->getLocation("lightColor"), m_color); int slot = PBRMaterial::NB_PBR_SLOTS;
brdfLUT->bind(slot);
shader->bindInteger(shader->getLocation("brdfLUT"), slot);
++slot;
ambient->bind(slot);
shader->bindInteger(shader->getLocation("ambientMap"), slot);
++slot;
reflect->bind(slot);
shader->bindInteger(shader->getLocation("reflectMap"), slot);
shader->bindMat3(shader->getLocation("inverseViewMatrix"), glm::inverse(glm::mat3(camera->getViewMatrix())));
} }
// DIRECTIONNAL LIGHT // DIRECTIONNAL LIGHT

View File

@ -51,11 +51,19 @@ protected:
class AmbientLight : public Light class AmbientLight : public Light
{ {
Texture* ambient;
Texture* reflect;
static Texture* brdfLUT;
public: public:
AmbientLight(glm::vec3 lightColor = glm::vec3(0.1f)) { m_color = lightColor; } AmbientLight(Texture* ambientTex = nullptr, Texture* reflectTex = nullptr) : ambient(ambientTex), reflect(reflectTex) {}
virtual LightType getType() { return AMBIENT; } virtual LightType getType() { return AMBIENT; }
virtual void bindAttributes(Shader *shader, Camera *camera); virtual void bindAttributes(Shader *shader, Camera *camera);
virtual unsigned int getFlags() { return 1 << AMBIENT_FLAG; } virtual unsigned int getFlags() { return 1 << AMBIENT_FLAG; }
void setAmbient(Texture* texture) { ambient = texture; }
Texture* getAmbient() { return ambient; }
void setReflect(Texture* texture) { reflect = texture; }
Texture* getReflect() { return reflect; }
static void setBrdfLut(Texture* texture) { brdfLUT = texture; }
}; };
class DirectionnalLight : public Light class DirectionnalLight : public Light

View File

@ -25,9 +25,10 @@ const char* const Mesh::flagStr[Mesh::NB_FLAGS] =
"ALPHA_MASK", "ALPHA_MASK",
"PHONG", "PHONG",
"DIFFUSE_TEXTURE", "ALBEDO_TEXTURE",
"EMISSION_TEXTURE", "EMISSION_TEXTURE",
"SPECULAR_TEXTURE", "ROUGHNESS_TEXTURE",
"METALLIC_TEXTURE",
"NORMAL_MAP", "NORMAL_MAP",
"BUMP_MAP" "BUMP_MAP"

View File

@ -41,15 +41,16 @@ public:
MATERIAL_COLOR_TEXTURE, MATERIAL_COLOR_TEXTURE,
MATERIAL_ALPHA_MASK, MATERIAL_ALPHA_MASK,
// 3D phong material // 3D PBR material
MATERIAL_PHONG, MATERIAL_PBR,
MATERIAL_PHONG_DIFFUSE_TEXTURE, MATERIAL_PBR_ALBEDO_TEXTURE,
MATERIAL_PHONG_EMISSION_TEXTURE, MATERIAL_PBR_EMISSION_TEXTURE,
MATERIAL_PHONG_SPECULAR_TEXTURE, MATERIAL_PBR_ROUGHNESS_TEXTURE,
MATERIAL_PHONG_NORMAL_MAP, MATERIAL_PBR_METALLIC_TEXTURE,
MATERIAL_PBR_NORMAL_MAP,
// 3D Beckman-like materials // 3D Beckman-like materials
MATERIAL_BACKMANN_BUMP_MAP, MATERIAL_BECKMANN_BUMP_MAP,
NB_FLAGS NB_FLAGS
}; };

View File

@ -1,93 +0,0 @@
#include "model.h"
#include "mesh.h"
#include "image.h"
#include "texture.h"
#include "phongmaterial.h"
Model::Model() : m_texPack(NULL) {}
Model::~Model()
{
initDestroy();
destroyGL();
for(Mesh *m : m_meshes)
delete m;
setTexturePack(NULL);
}
void Model::setTexturePack(TexturePack *texPack)
{
if(m_texPack != NULL)
delete m_texPack;
m_texPack = texPack;
}
void Model::initDestroy()
{
initGL();
for(Mesh* m : m_meshes)
m->clearData();
if(m_texPack != NULL)
m_texPack->initDestroyImages();
}
void Model::initGL()
{
for(Mesh* m : m_meshes)
m->initGL();
if(m_texPack != NULL)
m_texPack->initGL();
}
void Model::destroyGL()
{
for(Mesh* m : m_meshes)
m->destroyGL();
if(m_texPack != NULL)
m_texPack->destroyGL();
}
bool Model::save(const std::string &filename, const std::string &texturesPath)
{
// open file
std::FILE *file = std::fopen(filename.c_str(), "w");
if(file == NULL)
return false;
// write meshes and materials, there is no material sharing (1 mesh = 1 material)
bool ok = false;
int size = m_meshes.size();
if(std::fwrite(&size, sizeof(int), 1, file))
{
ok = true;
for(Mesh* m : m_meshes)
{
ok = ok && m->serialize(file);
PhongMaterial* mat = (PhongMaterial*)m->getMaterial();
ok = ok && mat->serialize(file);
}
std::fclose(file);
}
// saves the TexturePack
if(m_texPack != NULL)
ok = ok && m_texPack->save(texturesPath);
// finishing
return ok;
}
Model* Model::load(const std::string &filename, const std::string &texturesPath)
{
// open file
std::FILE *file = std::fopen(filename.c_str(), "r");
if(file == NULL)
return NULL;
bool ok = false;
// finishing
return NULL;
}

View File

@ -1,78 +0,0 @@
#ifndef MODEL_H
#define MODEL_H
#include <vector>
#include <string>
class Mesh;
class Image;
class TexturePack;
class Model
{
protected:
TexturePack *m_texPack;
std::vector<Mesh*> m_meshes;
public:
Model();
~Model();
void setTexturePack(TexturePack *texPack);
/**
* @brief addMesh adds a mesh to the mesh list
*/
void addMesh(Mesh *mesh) { m_meshes.push_back(mesh); }
/**
* @brief getMeshes returns the mesh array
*/
const std::vector<Mesh*>& getMeshes() { return m_meshes; }
/**
* @brief getImage returns the image which has the specified name, or NULL if there are no images of this name.
*/
//Image* getImage(const std::string &name);
/**
* @brief getTexture returns the texture which has the specified name, or NULL if there are no images of this name.
*/
//Texture* getTexture(const std::string &name);
/**
* @brief uploads meshes and images to GPU memory,
* then frees Mesh and Image memory in the RAM,
* so it stays allocated only in GPU memory.
*/
void initDestroy();
/**
* @brief initGL uploads image and mesh data to GPU memory
*/
void initGL();
/**
* @brief destroyGL frees the meshes and the textures from GPU memory
*/
void destroyGL();
/**
* @brief save saves the model on a file
* @param filename is the name of the resulting file
* @param texturesPath is the existing folder where the textures will be saved
* @return true if the save succeeded
*/
bool save(const std::string &filename, const std::string &texturesPath);
/**
* @brief load loads the model from a file
* @param filename is the name of the target file
* @param texturesPath is the existing folder where the textures will be gathered
* @return the model if the loading succeeded, or NULL if it failed
*/
static Model* load(const std::string &filename, const std::string &texturesPath);
};
#endif // MODEL_H

View File

@ -1,6 +1,6 @@
#include "parametricmesh.h" #include "parametricmesh.h"
#include "glm/ext.hpp" #include "glm/ext.hpp"
#include "phongmaterial.h" #include "pbrmaterial.h"
#define M_PI 3.14159265358979323846 #define M_PI 3.14159265358979323846
#define MAGIC_RATIO 0.37139f #define MAGIC_RATIO 0.37139f

75
src/pbrmaterial.cpp Normal file
View File

@ -0,0 +1,75 @@
#include "pbrmaterial.h"
#include "texture.h"
#include "sparrowrenderer.h"
#include "shader.h"
#include "mesh.h"
#include <glm/ext.hpp>
void PBRMaterial::bindAttributes(Shader* myShader)
{
// TODO store the attributes location
myShader->bindFloat(myShader->getLocation("opacity"), opacity);
if(textures[NORMALS_SLOT] != NULL)
{
textures[NORMALS_SLOT]->bind(NORMALS_SLOT);
myShader->bindInteger(myShader->getLocation("normalMap"), NORMALS_SLOT);
}
if(textures[EMISSION_SLOT] != NULL)
{
textures[EMISSION_SLOT]->bind(EMISSION_SLOT);
myShader->bindInteger(myShader->getLocation("emissionTexture"), EMISSION_SLOT);
}
else
myShader->bindVec3(myShader->getLocation("emission"), emission);
if(textures[ALBEDO_SLOT] != NULL)
{
textures[ALBEDO_SLOT]->bind(ALBEDO_SLOT);
myShader->bindInteger(myShader->getLocation("albedoTexture"), ALBEDO_SLOT);
}
else
myShader->bindVec3(myShader->getLocation("albedo"), albedo);
if(textures[ROUGHNESS_SLOT] != NULL)
{
textures[ROUGHNESS_SLOT]->bind(ROUGHNESS_SLOT);
myShader->bindInteger(myShader->getLocation("roughnessTexture"), ROUGHNESS_SLOT);
}
else
myShader->bindFloat(myShader->getLocation("roughness"), roughness);
if(textures[METALLIC_SLOT] != NULL)
{
textures[METALLIC_SLOT]->bind(METALLIC_SLOT);
myShader->bindInteger(myShader->getLocation("metallicTexture"), METALLIC_SLOT);
}
else
myShader->bindFloat(myShader->getLocation("metallic"), metallic);
if(textures[ALPHA_SLOT] != NULL)
{
textures[ALPHA_SLOT]->bind(ALPHA_SLOT);
myShader->bindInteger(myShader->getLocation("alphaMask"), ALPHA_SLOT);
}
}
unsigned int PBRMaterial::getFlags()
{
unsigned int flags = 1 << Mesh::MATERIAL_PBR;
if(textures[NORMALS_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PBR_NORMAL_MAP;
if(textures[EMISSION_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PBR_EMISSION_TEXTURE;
if(textures[ALBEDO_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PBR_ALBEDO_TEXTURE;
if(textures[ROUGHNESS_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PBR_ROUGHNESS_TEXTURE;
if(textures[METALLIC_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PBR_METALLIC_TEXTURE;
if(textures[ALPHA_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_ALPHA_MASK;
return flags;
}

52
src/pbrmaterial.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef PHONGMATERIAL_H
#define PHONGMATERIAL_H
#include "material.h"
#include "glm/vec3.hpp"
#include <string>
class Texture;
struct PBRMaterial : public Material
{
enum TextureSlots
{
ALBEDO_SLOT,
EMISSION_SLOT,
NORMALS_SLOT,
ROUGHNESS_SLOT,
METALLIC_SLOT,
ALPHA_SLOT,
NB_PBR_SLOTS
};
glm::vec3 emission;
glm::vec3 albedo;
float roughness;
float metallic;
float opacity;
Texture* textures[NB_PBR_SLOTS];
std::string textureNames[NB_PBR_SLOTS];
PBRMaterial() :
emission(0),
albedo(0.9f),
roughness(0.8f),
metallic(0.2),
opacity(1.f)
{
for(int i=0; i<NB_PBR_SLOTS; ++i)
textures[i] = NULL;
}
void setTexture(TextureSlots slot, Texture* texture = NULL, const std::string &name = "")
{ textures[slot] = texture; textureNames[slot] = name; }
virtual ~PBRMaterial() {}
virtual void bindAttributes(Shader* myShader);
virtual unsigned int getFlags();
};
#endif // PHONGMATERIAL_H

View File

@ -1,142 +0,0 @@
#include "phongmaterial.h"
#include "texture.h"
#include "sparrowrenderer.h"
#include "shader.h"
#include "mesh.h"
#include <glm/ext.hpp>
void PhongMaterial::bindAttributes(Shader* myShader)
{
// TODO store the attributes location
myShader->bindFloat(myShader->getLocation("materialNs"), shininess);
myShader->bindFloat(myShader->getLocation("opacity"), m_opacity);
if(textures[NORMALS_SLOT] != NULL)
{
textures[NORMALS_SLOT]->bind(NORMALS_SLOT);
myShader->bindInteger(myShader->getLocation("normalMap"), NORMALS_SLOT);
}
if(textures[EMISSION_SLOT] != NULL)
{
textures[EMISSION_SLOT]->bind(EMISSION_SLOT);
myShader->bindInteger(myShader->getLocation("emissionTexture"), EMISSION_SLOT);
}
else
myShader->bindVec3(myShader->getLocation("materialEmission"), emission);
if(textures[DIFFUSE_SLOT] != NULL)
{
textures[DIFFUSE_SLOT]->bind(DIFFUSE_SLOT);
myShader->bindInteger(myShader->getLocation("diffuseTexture"), DIFFUSE_SLOT);
}
else
myShader->bindVec3(myShader->getLocation("materialKd"), diffuse);
if(textures[SPECULAR_SLOT] != NULL)
{
textures[SPECULAR_SLOT]->bind(SPECULAR_SLOT);
myShader->bindInteger(myShader->getLocation("specularTexture"), SPECULAR_SLOT);
}
else
myShader->bindVec3(myShader->getLocation("materialKs"), specular);
if(textures[ALPHA_SLOT] != NULL)
{
textures[ALPHA_SLOT]->bind(ALPHA_SLOT);
myShader->bindInteger(myShader->getLocation("alphaMask"), ALPHA_SLOT);
}
}
unsigned int PhongMaterial::getFlags()
{
unsigned int flags = 1 << Mesh::MATERIAL_PHONG;
if(textures[NORMALS_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PHONG_NORMAL_MAP;
if(textures[EMISSION_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PHONG_EMISSION_TEXTURE;
if(textures[DIFFUSE_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PHONG_DIFFUSE_TEXTURE;
if(textures[SPECULAR_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_PHONG_SPECULAR_TEXTURE;
if(textures[ALPHA_SLOT] != NULL)
flags |= 1 << Mesh::MATERIAL_ALPHA_MASK;
return flags;
}
// serialisation methods :
struct MaterialHeader
{
glm::vec3 emission;
glm::vec3 diffuse;
glm::vec3 specular;
float shininess;
int textureLengths[PhongMaterial::NB_PHONG_SLOTS];
};
bool PhongMaterial::serialize(PhongMaterial* mat, FILE *file)
{
unsigned int flags = mat->getFlags();
if(!fwrite(&flags, sizeof(unsigned int), 1, file))
return false;
if(flags & (1 << Mesh::MATERIAL_PHONG))
{
MaterialHeader header;
header.emission = mat->emission;
header.diffuse = mat->diffuse;
header.specular = mat->specular;
header.shininess = mat->shininess;
for(int i=0; i<PhongMaterial::NB_PHONG_SLOTS; ++i)
{
if(mat->textures[i] != NULL)
header.textureLengths[i] = mat->textureNames[i].length()+1;
else
header.textureLengths[i] = 0;
}
if(!std::fwrite(&header, sizeof(MaterialHeader), 1, file))
return false;
for(int i=0; i<PhongMaterial::NB_PHONG_SLOTS; ++i)
{
if(header.textureLengths[i] > 0)
{
if(!std::fwrite(mat->textureNames[i].c_str(), header.textureLengths[i], 1, file))
return false;
}
}
}
return true;
}
PhongMaterial* PhongMaterial::deserialize(FILE *file)
{
int flags;
if(!std::fread(&flags, sizeof(int), 1, file))
return NULL;
MaterialHeader header;
if(!std::fread(&header, sizeof(MaterialHeader), 1, file))
return NULL;
PhongMaterial *mat = new PhongMaterial();
mat->diffuse = header.diffuse;
mat->emission = header.emission;
mat->specular = header.specular;
mat->shininess = header.shininess;
for(int i=0; i<PhongMaterial::NB_PHONG_SLOTS; ++i)
{
char str[256];
if(!std::fread(str, header.textureLengths[i], 1, file))
{ delete mat; return NULL; }
mat->textureNames[i] = std::string(str);
}
return mat;
}

View File

@ -1,66 +0,0 @@
#ifndef PHONGMATERIAL_H
#define PHONGMATERIAL_H
#include "material.h"
#include "glm/vec3.hpp"
#include <string>
class Texture;
struct PhongMaterial : public Material
{
enum TextureSlots
{
DIFFUSE_SLOT,
EMISSION_SLOT,
NORMALS_SLOT,
SPECULAR_SLOT,
ALPHA_SLOT,
NB_PHONG_SLOTS
};
glm::vec3 emission;
glm::vec3 diffuse;
glm::vec3 specular;
float shininess;
float m_opacity;
Texture* textures[NB_PHONG_SLOTS];
std::string textureNames[NB_PHONG_SLOTS];
PhongMaterial() :
emission(0),
diffuse(0.5f),
specular(0.5f),
shininess(10),
m_opacity(1.f)
{
for(int i=0; i<NB_PHONG_SLOTS; ++i)
textures[i] = NULL;
}
void setTexture(TextureSlots slot, Texture* texture = NULL, const std::string &name = "")
{ textures[slot] = texture; textureNames[slot] = name; }
virtual ~PhongMaterial() {}
virtual void bindAttributes(Shader* myShader);
virtual unsigned int getFlags();
/**
* @brief serializeMaterial saves a material to a file
* @return true if the save succeeded
*/
static bool serialize(PhongMaterial* mat, FILE *file);
bool serialize(FILE *file) { return serialize(this, file); }
/**
* @brief deserializeMaterial creates a material from reading a file,
* be careful, this method has no way to load the attached textures, so you must do it manually,
* however, you can use the texture names stored in the textureNames array to find which textures are requested.
* @return the material or NULL if the loading failed
*/
static PhongMaterial* deserialize(FILE *file);
};
#endif // PHONGMATERIAL_H

View File

@ -1,17 +1,15 @@
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
#include <glm/mat3x3.hpp> #include <glm/mat3x3.hpp>
#include <glm/ext.hpp> #include <glm/ext.hpp>
#include "skyboxmodule.h" #include "skybox.h"
#include "shader.h" #include "shader.h"
#include "texture.h" #include "texture.h"
#include "camera.h" #include "camera.h"
#include "framebuffer.h" #include "opengl.h"
#include "sparrowrenderer.h"
#define BUFFER_OFFSET(i) ((char *)NULL + (i)) #define BUFFER_OFFSET(i) ((char *)NULL + (i))
SkyboxModule::SkyboxModule(Texture* myCubeMap) Skybox::Skybox(Texture* myCubeMap)
{ {
cubeMap = myCubeMap; cubeMap = myCubeMap;
@ -20,39 +18,38 @@ SkyboxModule::SkyboxModule(Texture* myCubeMap)
glGenBuffers(2, vbos); glGenBuffers(2, vbos);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[0]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof(GLubyte), skyboxIndices, GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 36 * sizeof(GLubyte), skyboxIndices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), skyboxVertices, GL_STATIC_DRAW); glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(GLfloat), skyboxVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), BUFFER_OFFSET(0));
renderTarget = FrameBuffer::screen; glEnableVertexAttribArray(0);
shader = new Shader(vertSource, fragSource); shader = new Shader(vertSource, fragSource);
mvpLocation = shader->getLocation("MVP"); mvpLocation = shader->getLocation("MVP");
cubemapLocation = shader->getLocation("skybox");
glBindVertexArray(0); glBindVertexArray(0);
} }
SkyboxModule::~SkyboxModule() Skybox::~Skybox()
{ {
glDeleteVertexArrays(1, &vao); glDeleteVertexArrays(1, &vao);
glDeleteBuffers(2, vbos); glDeleteBuffers(2, vbos);
} }
void SkyboxModule::renderGL(Camera* myCamera, Scene* scene) void Skybox::renderGL(Camera* myCamera)
{ {
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
glm::mat4 viewMatrix = glm::mat4(glm::mat3(myCamera->getViewMatrix())); glm::mat4 viewMatrix = glm::mat4(glm::mat3(myCamera->getViewMatrix()));
glm::mat4 projectionMatrix = myCamera->getProjectionMatrix();
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
renderTarget->bindFBO();
shader->bind(); shader->bind();
shader->bindMat4(mvpLocation, projectionMatrix * viewMatrix); shader->bindMat4(mvpLocation, myCamera->getProjectionMatrix() * viewMatrix);
shader->bindInteger(cubemapLocation, 0);
cubeMap->bind(0); cubeMap->bind(0);
glBindVertexArray(vao); glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbos[1]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), BUFFER_OFFSET(0));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[0]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbos[0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL); glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL);
glBindVertexArray(0); glBindVertexArray(0);
@ -61,13 +58,7 @@ void SkyboxModule::renderGL(Camera* myCamera, Scene* scene)
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
} }
void SkyboxModule::setRenderTarget(const FrameBuffer* target) const GLfloat Skybox::skyboxVertices[] = {
{
if(target != NULL)
renderTarget = target;
}
const GLfloat SkyboxModule::skyboxVertices[] = {
-1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f,
@ -78,7 +69,7 @@ const GLfloat SkyboxModule::skyboxVertices[] = {
1.0f, -1.0f, -1.0f 1.0f, -1.0f, -1.0f
}; };
const GLubyte SkyboxModule::skyboxIndices[] = { const GLubyte Skybox::skyboxIndices[] = {
0, 6, 2, 0, 6, 2,
0, 4, 6, 0, 4, 6,
1, 3, 5, 1, 3, 5,
@ -93,8 +84,9 @@ const GLubyte SkyboxModule::skyboxIndices[] = {
6, 7, 3 6, 7, 3
}; };
const std::string SkyboxModule::vertSource = const std::string Skybox::vertSource =
"layout(location = 0)in vec3 inPosition;\n\ "#version 330 core\n\
layout(location = 0)in vec3 inPosition;\n\
out vec3 varTexCoord;\n\ out vec3 varTexCoord;\n\
uniform mat4 MVP;\n\ uniform mat4 MVP;\n\
void main()\n\ void main()\n\
@ -103,8 +95,9 @@ const std::string SkyboxModule::vertSource =
varTexCoord = inPosition;\n\ varTexCoord = inPosition;\n\
}\n"; }\n";
const std::string SkyboxModule::fragSource = const std::string Skybox::fragSource =
"in vec3 varTexCoord;\n\ "#version 330 core\n\
in vec3 varTexCoord;\n\
out vec4 outColor;\n\ out vec4 outColor;\n\
uniform samplerCube skybox;\n\ uniform samplerCube skybox;\n\
void main()\n\ void main()\n\

35
src/skybox.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef SKYBOX_H
#define SKYBOX_H
#include "opengl.h"
#include <string>
class Camera;
class Shader;
class Texture;
class Skybox
{
static const GLfloat skyboxVertices[];
static const GLubyte skyboxIndices[];
static const std::string vertSource;
static const std::string fragSource;
int width;
int height;
GLuint vao;
GLuint vbos[2];
GLuint mvpLocation;
GLuint cubemapLocation;
Shader* shader;
Texture* cubeMap;
public:
Skybox(Texture* myCubeMap);
~Skybox();
void renderGL(Camera* myCamera);
void resizeGL(int w, int h) {width = w; height = h;}
};
#endif // SKYBOX_H

View File

@ -1,38 +0,0 @@
#ifndef SKYBOXMODULE_H
#define SKYBOXMODULE_H
#include "opengl.h"
#include "module.h"
#include <string>
class Shader;
class Texture;
class FrameBuffer;
class SkyboxModule : public Module
{
static const GLfloat skyboxVertices[];
static const GLubyte skyboxIndices[];
static const std::string vertSource;
static const std::string fragSource;
int width;
int height;
GLuint vao;
GLuint vbos[2];
GLuint mvpLocation;
Shader* shader;
Texture* cubeMap;
const FrameBuffer* renderTarget;
public:
SkyboxModule(Texture* myCubeMap);
~SkyboxModule();
virtual void renderGL(Camera* myCamera, Scene* scene = NULL);
virtual void resize(int w, int h) {width = w; height = h;}
void setRenderTarget(const FrameBuffer* target);
};
#endif // SKYBOXMODULE_H