diff --git a/ACKNOWLEDGEMENTS.html b/ACKNOWLEDGEMENTS.html
index 8beecfcb..39a2c273 100644
--- a/ACKNOWLEDGEMENTS.html
+++ b/ACKNOWLEDGEMENTS.html
@@ -1296,4 +1296,9 @@ https://www.reddit.com/r/gamedev/comments/5iuf3h/i_am_writting_a_3d_monster_mode
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+
+
+
Greg Zaal
+
+ https://hdrihaven.com/hdri/?h=cedar_bridge
\ No newline at end of file
diff --git a/dust3d.pro b/dust3d.pro
index 48c8db83..5fff1c41 100644
--- a/dust3d.pro
+++ b/dust3d.pro
@@ -505,6 +505,9 @@ HEADERS += src/projectfacestonodes.h
SOURCES += src/simulateclothmeshes.cpp
HEADERS += src/simulateclothmeshes.h
+SOURCES += src/ddsfile.cpp
+HEADERS += src/ddsfile.h
+
SOURCES += src/main.cpp
HEADERS += src/version.h
diff --git a/resources.qrc b/resources.qrc
index 3b0ebb54..3fab310b 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -23,6 +23,8 @@
resources/heptagon.png
resources/userdefined.png
resources/checkuv.png
+ resources/cedar_bridge_irradiance.dds
+ resources/cedar_bridge_specular.dds
shaders/default.vert
shaders/default.frag
shaders/default.core.vert
diff --git a/resources/cedar_bridge_irradiance.dds b/resources/cedar_bridge_irradiance.dds
new file mode 100644
index 00000000..c08c4630
Binary files /dev/null and b/resources/cedar_bridge_irradiance.dds differ
diff --git a/resources/cedar_bridge_specular.dds b/resources/cedar_bridge_specular.dds
new file mode 100644
index 00000000..ac9d49cc
Binary files /dev/null and b/resources/cedar_bridge_specular.dds differ
diff --git a/shaders/default.core.frag b/shaders/default.core.frag
index 3bf72812..41c6a8f6 100644
--- a/shaders/default.core.frag
+++ b/shaders/default.core.frag
@@ -53,35 +53,39 @@
// https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag
// Exposure correction
-highp float exposure;
+float exposure;
// Gamma correction
-highp float gamma;
+float gamma;
-in highp vec3 vert;
-in highp vec3 vertRaw;
-in highp vec3 vertNormal;
-in highp vec3 vertColor;
-in highp vec2 vertTexCoord;
-in highp float vertMetalness;
-in highp float vertRoughness;
-in highp vec3 cameraPos;
-in highp vec3 firstLightPos;
-in highp vec3 secondLightPos;
-in highp vec3 thirdLightPos;
-in highp float vertAlpha;
-out highp vec4 fragColor;
-uniform highp vec3 lightPos;
-uniform highp sampler2D textureId;
-uniform highp int textureEnabled;
-uniform highp sampler2D normalMapId;
-uniform highp int normalMapEnabled;
-uniform highp sampler2D metalnessRoughnessAmbientOcclusionMapId;
-uniform highp int metalnessMapEnabled;
-uniform highp int roughnessMapEnabled;
-uniform highp int ambientOcclusionMapEnabled;
-uniform highp int mousePickEnabled;
-uniform highp vec3 mousePickTargetPosition;
-uniform highp float mousePickRadius;
+in vec3 vert;
+in vec3 vertRaw;
+in vec3 vertNormal;
+in vec3 vertColor;
+in vec2 vertTexCoord;
+in float vertMetalness;
+in float vertRoughness;
+in vec3 cameraPos;
+in vec3 firstLightPos;
+in vec3 secondLightPos;
+in vec3 thirdLightPos;
+in float vertAlpha;
+out vec4 fragColor;
+uniform vec3 lightPos;
+uniform sampler2D textureId;
+uniform int textureEnabled;
+uniform sampler2D normalMapId;
+uniform int normalMapEnabled;
+uniform sampler2D metalnessRoughnessAmbientOcclusionMapId;
+uniform int metalnessMapEnabled;
+uniform int roughnessMapEnabled;
+uniform int ambientOcclusionMapEnabled;
+uniform int mousePickEnabled;
+uniform vec3 mousePickTargetPosition;
+uniform float mousePickRadius;
+uniform samplerCube environmentIrradianceMapId;
+uniform int environmentIrradianceMapEnabled;
+uniform samplerCube environmentSpecularMapId;
+uniform int environmentSpecularMapEnabled;
const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0;
@@ -89,51 +93,88 @@ const int TYPE_DIRECTIONAL = 1;
const int TYPE_SPOT = 2;
struct Light {
int type;
- highp vec3 position;
- highp vec3 color;
- highp float intensity;
- highp vec3 direction;
- highp float constantAttenuation;
- highp float linearAttenuation;
- highp float quadraticAttenuation;
- highp float cutOffAngle;
+ vec3 position;
+ vec3 color;
+ float intensity;
+ vec3 direction;
+ float constantAttenuation;
+ float linearAttenuation;
+ float quadraticAttenuation;
+ float cutOffAngle;
};
int lightCount;
Light lights[MAX_LIGHTS];
-highp float remapRoughness(const in highp float roughness)
+int mipLevelCount(const in samplerCube cube)
+{
+ int baseSize = textureSize(cube, 0).x;
+ int nMips = int(log2(float(baseSize > 0 ? baseSize : 1))) + 1;
+ return nMips;
+}
+
+float remapRoughness(const in float roughness)
{
// As per page 14 of
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
// we remap the roughness to give a more perceptually linear response
// of "bluriness" as a function of the roughness specified by the user.
// r = roughness^2
- highp float maxSpecPower;
- highp float minRoughness;
+ float maxSpecPower;
+ float minRoughness;
maxSpecPower = 999999.0;
minRoughness = sqrt(2.0 / (maxSpecPower + 2.0));
return max(roughness * roughness, minRoughness);
}
-highp float normalDistribution(const in highp vec3 n, const in highp vec3 h, const in highp float alpha)
+float alphaToMipLevel(float alpha)
+{
+ float specPower = 2.0 / (alpha * alpha) - 2.0;
+
+ // We use the mip level calculation from Lys' default power drop, which in
+ // turn is a slight modification of that used in Marmoset Toolbag. See
+ // https://docs.knaldtech.com/doku.php?id=specular_lys for details.
+ // For now we assume a max specular power of 999999 which gives
+ // maxGlossiness = 1.
+ const float k0 = 0.00098;
+ const float k1 = 0.9921;
+ float glossiness = (pow(2.0, -10.0 / sqrt(specPower)) - k0) / k1;
+
+ // TODO: Optimize by doing this on CPU and set as
+ // uniform int environmentSpecularMapIdMipLevels say (if present in shader).
+ // Lookup the number of mips in the specular envmap
+ int mipLevels = mipLevelCount(environmentSpecularMapId);
+
+ // Offset of smallest miplevel we should use (corresponds to specular
+ // power of 1). I.e. in the 32x32 sized mip.
+ const float mipOffset = 5.0;
+
+ // The final factor is really 1 - g / g_max but as mentioned above g_max
+ // is 1 by definition here so we can avoid the division. If we make the
+ // max specular power for the spec map configurable, this will need to
+ // be handled properly.
+ float mipLevel = (mipLevels - 1.0 - mipOffset) * (1.0 - glossiness);
+ return mipLevel;
+}
+
+float normalDistribution(const in vec3 n, const in vec3 h, const in float alpha)
{
// Blinn-Phong approximation - see
// http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html
- highp float specPower = 2.0 / (alpha * alpha) - 2.0;
+ float specPower = 2.0 / (alpha * alpha) - 2.0;
return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower);
}
-highp vec3 fresnelFactor(const in highp vec3 color, const in highp float cosineFactor)
+vec3 fresnelFactor(const in vec3 color, const in float cosineFactor)
{
// Calculate the Fresnel effect value
- highp vec3 f = color;
- highp vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
+ vec3 f = color;
+ vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
return clamp(F, f, vec3(1.0));
}
-highp float geometricModel(const in highp float lDotN,
- const in highp float vDotN,
- const in highp vec3 h)
+float geometricModel(const in float lDotN,
+ const in float vDotN,
+ const in vec3 h)
{
// Implicit geometric model (equal to denominator in specular model).
// This currently assumes that there is no attenuation by geometric shadowing or
@@ -141,50 +182,50 @@ highp float geometricModel(const in highp float lDotN,
return lDotN * vDotN;
}
-highp vec3 specularModel(const in highp vec3 F0,
- const in highp float sDotH,
- const in highp float sDotN,
- const in highp float vDotN,
- const in highp vec3 n,
- const in highp vec3 h)
+vec3 specularModel(const in vec3 F0,
+ const in float sDotH,
+ const in float sDotN,
+ const in float vDotN,
+ const in vec3 n,
+ const in vec3 h)
{
// Clamp sDotN and vDotN to small positive value to prevent the
// denominator in the reflection equation going to infinity. Balance this
// by using the clamped values in the geometric factor function to
// avoid ugly seams in the specular lighting.
- highp float sDotNPrime = max(sDotN, 0.001);
- highp float vDotNPrime = max(vDotN, 0.001);
+ float sDotNPrime = max(sDotN, 0.001);
+ float vDotNPrime = max(vDotN, 0.001);
- highp vec3 F = fresnelFactor(F0, sDotH);
- highp float G = geometricModel(sDotNPrime, vDotNPrime, h);
+ vec3 F = fresnelFactor(F0, sDotH);
+ float G = geometricModel(sDotNPrime, vDotNPrime, h);
- highp vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime);
+ vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime);
return clamp(cSpec, vec3(0.0), vec3(1.0));
}
-highp vec3 pbrModel(const in int lightIndex,
- const in highp vec3 wPosition,
- const in highp vec3 wNormal,
- const in highp vec3 wView,
- const in highp vec3 baseColor,
- const in highp float metalness,
- const in highp float alpha,
- const in highp float ambientOcclusion)
+vec3 pbrModel(const in int lightIndex,
+ const in vec3 wPosition,
+ const in vec3 wNormal,
+ const in vec3 wView,
+ const in vec3 baseColor,
+ const in float metalness,
+ const in float alpha,
+ const in float ambientOcclusion)
{
// Calculate some useful quantities
- highp vec3 n = wNormal;
- highp vec3 s = vec3(0.0);
- highp vec3 v = wView;
- highp vec3 h = vec3(0.0);
+ vec3 n = wNormal;
+ vec3 s = vec3(0.0);
+ vec3 v = wView;
+ vec3 h = vec3(0.0);
- highp float vDotN = dot(v, n);
- highp float sDotN = 0.0;
- highp float sDotH = 0.0;
- highp float att = 1.0;
+ float vDotN = dot(v, n);
+ float sDotN = 0.0;
+ float sDotH = 0.0;
+ float att = 1.0;
if (lights[lightIndex].type != TYPE_DIRECTIONAL) {
// Point and Spot lights
- highp vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition;
+ vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition;
s = normalize(sUnnormalized);
// Calculate the attenuation factor
@@ -193,7 +234,7 @@ highp vec3 pbrModel(const in int lightIndex,
if (lights[lightIndex].constantAttenuation != 0.0
|| lights[lightIndex].linearAttenuation != 0.0
|| lights[lightIndex].quadraticAttenuation != 0.0) {
- highp float dist = length(sUnnormalized);
+ float dist = length(sUnnormalized);
att = 1.0 / (lights[lightIndex].constantAttenuation +
lights[lightIndex].linearAttenuation * dist +
lights[lightIndex].quadraticAttenuation * dist * dist);
@@ -217,22 +258,22 @@ highp vec3 pbrModel(const in int lightIndex,
sDotH = dot(s, h);
// Calculate diffuse component
- highp vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
- highp vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
+ vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
+ vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
// Calculate specular component
- highp vec3 dielectricColor = vec3(0.04);
- highp vec3 F0 = mix(dielectricColor, baseColor, metalness);
- highp vec3 specularFactor = vec3(0.0);
+ vec3 dielectricColor = vec3(0.04);
+ vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ vec3 specularFactor = vec3(0.0);
if (sDotN > 0.0) {
specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h);
specularFactor *= normalDistribution(n, h, alpha);
}
- highp vec3 specularColor = lights[lightIndex].color;
- highp vec3 specular = specularColor * specularFactor;
+ vec3 specularColor = lights[lightIndex].color;
+ vec3 specular = specularColor * specularFactor;
// Blend between diffuse and specular to conserver energy
- highp vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular));
+ vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular));
// Reduce by ambient occlusion amount
color *= ambientOcclusion;
@@ -240,29 +281,99 @@ highp vec3 pbrModel(const in int lightIndex,
return color;
}
-highp vec3 toneMap(const in highp vec3 c)
+vec3 pbrIblModel(const in vec3 wNormal,
+ const in vec3 wView,
+ const in vec3 baseColor,
+ const in float metalness,
+ const in float alpha,
+ const in float ambientOcclusion)
+{
+ // Calculate reflection direction of view vector about surface normal
+ // vector in world space. This is used in the fragment shader to sample
+ // from the environment textures for a light source. This is equivalent
+ // to the l vector for punctual light sources. Armed with this, calculate
+ // the usual factors needed
+ vec3 n = wNormal;
+ vec3 l = reflect(-wView, n);
+ vec3 v = wView;
+ vec3 h = normalize(l + v);
+ float vDotN = dot(v, n);
+ float lDotN = dot(l, n);
+ float lDotH = dot(l, h);
+
+ // Calculate diffuse component
+ vec3 diffuseColor = (1.0 - metalness) * baseColor;
+ vec3 diffuse = diffuseColor * texture(environmentIrradianceMapId, l).rgb;
+
+ // Calculate specular component
+ vec3 dielectricColor = vec3(0.04);
+ vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ vec3 specularFactor = specularModel(F0, lDotH, lDotN, vDotN, n, h);
+
+ float lod = alphaToMipLevel(alpha);
+//#define DEBUG_SPECULAR_LODS
+#ifdef DEBUG_SPECULAR_LODS
+ if (lod > 7.0)
+ return vec3(1.0, 0.0, 0.0);
+ else if (lod > 6.0)
+ return vec3(1.0, 0.333, 0.0);
+ else if (lod > 5.0)
+ return vec3(1.0, 1.0, 0.0);
+ else if (lod > 4.0)
+ return vec3(0.666, 1.0, 0.0);
+ else if (lod > 3.0)
+ return vec3(0.0, 1.0, 0.666);
+ else if (lod > 2.0)
+ return vec3(0.0, 0.666, 1.0);
+ else if (lod > 1.0)
+ return vec3(0.0, 0.0, 1.0);
+ else if (lod > 0.0)
+ return vec3(1.0, 0.0, 1.0);
+#endif
+ vec3 specularSkyColor = textureLod(environmentSpecularMapId, l, lod).rgb;
+ vec3 specular = specularSkyColor * specularFactor;
+
+ // Blend between diffuse and specular to conserve energy
+ vec3 color = specular + diffuse * (vec3(1.0) - specularFactor);
+
+ // Reduce by ambient occlusion amount
+ color *= ambientOcclusion;
+
+ return color;
+}
+
+vec3 toneMap(const in vec3 c)
{
return c / (c + vec3(1.0));
}
-highp vec3 gammaCorrect(const in highp vec3 color)
+vec3 gammaCorrect(const in vec3 color)
{
return pow(color, vec3(1.0 / gamma));
}
-highp vec4 metalRoughFunction(const in highp vec4 baseColor,
- const in highp float metalness,
- const in highp float roughness,
- const in highp float ambientOcclusion,
- const in highp vec3 worldPosition,
- const in highp vec3 worldView,
- const in highp vec3 worldNormal)
+vec4 metalRoughFunction(const in vec4 baseColor,
+ const in float metalness,
+ const in float roughness,
+ const in float ambientOcclusion,
+ const in vec3 worldPosition,
+ const in vec3 worldView,
+ const in vec3 worldNormal)
{
- highp vec3 cLinear = vec3(0.0);
+ vec3 cLinear = vec3(0.0);
// Remap roughness for a perceptually more linear correspondence
- highp float alpha = remapRoughness(roughness);
-
+ float alpha = remapRoughness(roughness);
+
+ if (environmentIrradianceMapEnabled == 1) {
+ cLinear += pbrIblModel(worldNormal,
+ worldView,
+ baseColor.rgb,
+ metalness,
+ alpha,
+ ambientOcclusion);
+ }
+
for (int i = 0; i < lightCount; ++i) {
cLinear += pbrModel(i,
worldPosition,
@@ -278,10 +389,10 @@ highp vec4 metalRoughFunction(const in highp vec4 baseColor,
cLinear *= pow(2.0, exposure);
// Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1]
- highp vec3 cToneMapped = toneMap(cLinear);
+ vec3 cToneMapped = toneMap(cLinear);
// Apply gamma correction prior to display
- highp vec3 cGamma = gammaCorrect(cToneMapped);
+ vec3 cGamma = gammaCorrect(cToneMapped);
return vec4(cGamma, baseColor.a);
}
@@ -323,10 +434,10 @@ void main()
lights[2].linearAttenuation = 0.0;
lights[2].quadraticAttenuation = 0.0;
- highp vec3 color = vertColor;
- highp float alpha = vertAlpha;
+ vec3 color = vertColor;
+ float alpha = vertAlpha;
if (textureEnabled == 1) {
- highp vec4 textColor = texture(textureId, vertTexCoord);
+ vec4 textColor = texture(textureId, vertTexCoord);
color = textColor.rgb;
alpha = textColor.a;
}
@@ -337,7 +448,7 @@ void main()
}
color = pow(color, vec3(gamma));
- highp vec3 normal = vertNormal;
+ vec3 normal = vertNormal;
if (normalMapEnabled == 1) {
normal = texture(normalMapId, vertTexCoord).rgb;
normal = normalize(normal * 2.0 - 1.0);
@@ -347,23 +458,25 @@ void main()
// Green: Roughness
// Blue: Metallic
- highp float metalness = vertMetalness;
+ float metalness = vertMetalness;
if (metalnessMapEnabled == 1) {
metalness = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b;
}
- highp float roughness = vertRoughness;
+ float roughness = vertRoughness;
if (roughnessMapEnabled == 1) {
roughness = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g;
}
- highp float ambientOcclusion = 1.0;
+ float ambientOcclusion = 1.0;
if (ambientOcclusionMapEnabled == 1) {
ambientOcclusion = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r;
}
- roughness = min(0.99, roughness);
- metalness = min(0.99, metalness);
+ if (environmentIrradianceMapEnabled != 1) {
+ roughness = min(0.99, roughness);
+ metalness = min(0.99, metalness);
+ }
fragColor = metalRoughFunction(vec4(color, alpha),
metalness,
diff --git a/shaders/default.core.vert b/shaders/default.core.vert
index 2955b5c1..210e1e83 100644
--- a/shaders/default.core.vert
+++ b/shaders/default.core.vert
@@ -1,29 +1,29 @@
#version 330
-layout(location = 0) in highp vec4 vertex;
-layout(location = 1) in highp vec3 normal;
-layout(location = 2) in highp vec3 color;
-layout(location = 3) in highp vec2 texCoord;
-layout(location = 4) in highp float metalness;
-layout(location = 5) in highp float roughness;
-layout(location = 6) in highp vec3 tangent;
-layout(location = 7) in highp float alpha;
-out highp vec3 vert;
-out highp vec3 vertRaw;
-out highp vec3 vertNormal;
-out highp vec3 vertColor;
-out highp vec2 vertTexCoord;
-out highp float vertMetalness;
-out highp float vertRoughness;
-out highp vec3 cameraPos;
-out highp vec3 firstLightPos;
-out highp vec3 secondLightPos;
-out highp vec3 thirdLightPos;
-out highp float vertAlpha;
-uniform highp mat4 projectionMatrix;
-uniform highp mat4 modelMatrix;
-uniform highp mat3 normalMatrix;
-uniform highp mat4 viewMatrix;
-uniform highp int normalMapEnabled;
+layout(location = 0) in vec4 vertex;
+layout(location = 1) in vec3 normal;
+layout(location = 2) in vec3 color;
+layout(location = 3) in vec2 texCoord;
+layout(location = 4) in float metalness;
+layout(location = 5) in float roughness;
+layout(location = 6) in vec3 tangent;
+layout(location = 7) in float alpha;
+out vec3 vert;
+out vec3 vertRaw;
+out vec3 vertNormal;
+out vec3 vertColor;
+out vec2 vertTexCoord;
+out float vertMetalness;
+out float vertRoughness;
+out vec3 cameraPos;
+out vec3 firstLightPos;
+out vec3 secondLightPos;
+out vec3 thirdLightPos;
+out float vertAlpha;
+uniform mat4 projectionMatrix;
+uniform mat4 modelMatrix;
+uniform mat3 normalMatrix;
+uniform mat4 viewMatrix;
+uniform int normalMapEnabled;
mat3 transpose(mat3 m)
{
diff --git a/shaders/default.frag b/shaders/default.frag
index 401f7b56..6a1c225e 100644
--- a/shaders/default.frag
+++ b/shaders/default.frag
@@ -52,34 +52,34 @@
// https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag
// Exposure correction
-highp float exposure;
+float exposure;
// Gamma correction
-highp float gamma;
+float gamma;
-varying highp vec3 vert;
-varying highp vec3 vertRaw;
-varying highp vec3 vertNormal;
-varying highp vec3 vertColor;
-varying highp vec2 vertTexCoord;
-varying highp float vertMetalness;
-varying highp float vertRoughness;
-varying highp vec3 cameraPos;
-varying highp vec3 firstLightPos;
-varying highp vec3 secondLightPos;
-varying highp vec3 thirdLightPos;
-varying highp float vertAlpha;
-uniform highp vec3 lightPos;
-uniform highp sampler2D textureId;
-uniform highp int textureEnabled;
-uniform highp sampler2D normalMapId;
-uniform highp int normalMapEnabled;
-uniform highp sampler2D metalnessRoughnessAmbientOcclusionMapId;
-uniform highp int metalnessMapEnabled;
-uniform highp int roughnessMapEnabled;
-uniform highp int ambientOcclusionMapEnabled;
-uniform highp int mousePickEnabled;
-uniform highp vec3 mousePickTargetPosition;
-uniform highp float mousePickRadius;
+varying vec3 vert;
+varying vec3 vertRaw;
+varying vec3 vertNormal;
+varying vec3 vertColor;
+varying vec2 vertTexCoord;
+varying float vertMetalness;
+varying float vertRoughness;
+varying vec3 cameraPos;
+varying vec3 firstLightPos;
+varying vec3 secondLightPos;
+varying vec3 thirdLightPos;
+varying float vertAlpha;
+uniform vec3 lightPos;
+uniform sampler2D textureId;
+uniform int textureEnabled;
+uniform sampler2D normalMapId;
+uniform int normalMapEnabled;
+uniform sampler2D metalnessRoughnessAmbientOcclusionMapId;
+uniform int metalnessMapEnabled;
+uniform int roughnessMapEnabled;
+uniform int ambientOcclusionMapEnabled;
+uniform int mousePickEnabled;
+uniform vec3 mousePickTargetPosition;
+uniform float mousePickRadius;
const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0;
@@ -87,51 +87,51 @@ const int TYPE_DIRECTIONAL = 1;
const int TYPE_SPOT = 2;
struct Light {
int type;
- highp vec3 position;
- highp vec3 color;
- highp float intensity;
- highp vec3 direction;
- highp float constantAttenuation;
- highp float linearAttenuation;
- highp float quadraticAttenuation;
- highp float cutOffAngle;
+ vec3 position;
+ vec3 color;
+ float intensity;
+ vec3 direction;
+ float constantAttenuation;
+ float linearAttenuation;
+ float quadraticAttenuation;
+ float cutOffAngle;
};
int lightCount;
Light lights[MAX_LIGHTS];
-highp float remapRoughness(const in highp float roughness)
+float remapRoughness(const in float roughness)
{
// As per page 14 of
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
// we remap the roughness to give a more perceptually linear response
// of "bluriness" as a function of the roughness specified by the user.
// r = roughness^2
- highp float maxSpecPower;
- highp float minRoughness;
+ float maxSpecPower;
+ float minRoughness;
maxSpecPower = 999999.0;
minRoughness = sqrt(2.0 / (maxSpecPower + 2.0));
return max(roughness * roughness, minRoughness);
}
-highp float normalDistribution(const in highp vec3 n, const in highp vec3 h, const in highp float alpha)
+float normalDistribution(const in vec3 n, const in vec3 h, const in float alpha)
{
// Blinn-Phong approximation - see
// http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html
- highp float specPower = 2.0 / (alpha * alpha) - 2.0;
+ float specPower = 2.0 / (alpha * alpha) - 2.0;
return (specPower + 2.0) / (2.0 * 3.14159) * pow(max(dot(n, h), 0.0), specPower);
}
-highp vec3 fresnelFactor(const in highp vec3 color, const in highp float cosineFactor)
+vec3 fresnelFactor(const in vec3 color, const in float cosineFactor)
{
// Calculate the Fresnel effect value
- highp vec3 f = color;
- highp vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
+ vec3 f = color;
+ vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
return clamp(F, f, vec3(1.0));
}
-highp float geometricModel(const in highp float lDotN,
- const in highp float vDotN,
- const in highp vec3 h)
+float geometricModel(const in float lDotN,
+ const in float vDotN,
+ const in vec3 h)
{
// Implicit geometric model (equal to denominator in specular model).
// This currently assumes that there is no attenuation by geometric shadowing or
@@ -139,50 +139,50 @@ highp float geometricModel(const in highp float lDotN,
return lDotN * vDotN;
}
-highp vec3 specularModel(const in highp vec3 F0,
- const in highp float sDotH,
- const in highp float sDotN,
- const in highp float vDotN,
- const in highp vec3 n,
- const in highp vec3 h)
+vec3 specularModel(const in vec3 F0,
+ const in float sDotH,
+ const in float sDotN,
+ const in float vDotN,
+ const in vec3 n,
+ const in vec3 h)
{
// Clamp sDotN and vDotN to small positive value to prevent the
// denominator in the reflection equation going to infinity. Balance this
// by using the clamped values in the geometric factor function to
// avoid ugly seams in the specular lighting.
- highp float sDotNPrime = max(sDotN, 0.001);
- highp float vDotNPrime = max(vDotN, 0.001);
+ float sDotNPrime = max(sDotN, 0.001);
+ float vDotNPrime = max(vDotN, 0.001);
- highp vec3 F = fresnelFactor(F0, sDotH);
- highp float G = geometricModel(sDotNPrime, vDotNPrime, h);
+ vec3 F = fresnelFactor(F0, sDotH);
+ float G = geometricModel(sDotNPrime, vDotNPrime, h);
- highp vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime);
+ vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime);
return clamp(cSpec, vec3(0.0), vec3(1.0));
}
-highp vec3 pbrModel(const in int lightIndex,
- const in highp vec3 wPosition,
- const in highp vec3 wNormal,
- const in highp vec3 wView,
- const in highp vec3 baseColor,
- const in highp float metalness,
- const in highp float alpha,
- const in highp float ambientOcclusion)
+vec3 pbrModel(const in int lightIndex,
+ const in vec3 wPosition,
+ const in vec3 wNormal,
+ const in vec3 wView,
+ const in vec3 baseColor,
+ const in float metalness,
+ const in float alpha,
+ const in float ambientOcclusion)
{
// Calculate some useful quantities
- highp vec3 n = wNormal;
- highp vec3 s = vec3(0.0);
- highp vec3 v = wView;
- highp vec3 h = vec3(0.0);
+ vec3 n = wNormal;
+ vec3 s = vec3(0.0);
+ vec3 v = wView;
+ vec3 h = vec3(0.0);
- highp float vDotN = dot(v, n);
- highp float sDotN = 0.0;
- highp float sDotH = 0.0;
- highp float att = 1.0;
+ float vDotN = dot(v, n);
+ float sDotN = 0.0;
+ float sDotH = 0.0;
+ float att = 1.0;
if (lights[lightIndex].type != TYPE_DIRECTIONAL) {
// Point and Spot lights
- highp vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition;
+ vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition;
s = normalize(sUnnormalized);
// Calculate the attenuation factor
@@ -191,7 +191,7 @@ highp vec3 pbrModel(const in int lightIndex,
if (lights[lightIndex].constantAttenuation != 0.0
|| lights[lightIndex].linearAttenuation != 0.0
|| lights[lightIndex].quadraticAttenuation != 0.0) {
- highp float dist = length(sUnnormalized);
+ float dist = length(sUnnormalized);
att = 1.0 / (lights[lightIndex].constantAttenuation +
lights[lightIndex].linearAttenuation * dist +
lights[lightIndex].quadraticAttenuation * dist * dist);
@@ -215,22 +215,22 @@ highp vec3 pbrModel(const in int lightIndex,
sDotH = dot(s, h);
// Calculate diffuse component
- highp vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
- highp vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
+ vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
+ vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
// Calculate specular component
- highp vec3 dielectricColor = vec3(0.04);
- highp vec3 F0 = mix(dielectricColor, baseColor, metalness);
- highp vec3 specularFactor = vec3(0.0);
+ vec3 dielectricColor = vec3(0.04);
+ vec3 F0 = mix(dielectricColor, baseColor, metalness);
+ vec3 specularFactor = vec3(0.0);
if (sDotN > 0.0) {
specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h);
specularFactor *= normalDistribution(n, h, alpha);
}
- highp vec3 specularColor = lights[lightIndex].color;
- highp vec3 specular = specularColor * specularFactor;
+ vec3 specularColor = lights[lightIndex].color;
+ vec3 specular = specularColor * specularFactor;
// Blend between diffuse and specular to conserver energy
- highp vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular));
+ vec3 color = att * lights[lightIndex].intensity * (specular + diffuse * (vec3(1.0) - specular));
// Reduce by ambient occlusion amount
color *= ambientOcclusion;
@@ -238,28 +238,28 @@ highp vec3 pbrModel(const in int lightIndex,
return color;
}
-highp vec3 toneMap(const in highp vec3 c)
+vec3 toneMap(const in vec3 c)
{
return c / (c + vec3(1.0));
}
-highp vec3 gammaCorrect(const in highp vec3 color)
+vec3 gammaCorrect(const in vec3 color)
{
return pow(color, vec3(1.0 / gamma));
}
-highp vec4 metalRoughFunction(const in highp vec4 baseColor,
- const in highp float metalness,
- const in highp float roughness,
- const in highp float ambientOcclusion,
- const in highp vec3 worldPosition,
- const in highp vec3 worldView,
- const in highp vec3 worldNormal)
+vec4 metalRoughFunction(const in vec4 baseColor,
+ const in float metalness,
+ const in float roughness,
+ const in float ambientOcclusion,
+ const in vec3 worldPosition,
+ const in vec3 worldView,
+ const in vec3 worldNormal)
{
- highp vec3 cLinear = vec3(0.0);
+ vec3 cLinear = vec3(0.0);
// Remap roughness for a perceptually more linear correspondence
- highp float alpha = remapRoughness(roughness);
+ float alpha = remapRoughness(roughness);
for (int i = 0; i < lightCount; ++i) {
cLinear += pbrModel(i,
@@ -276,10 +276,10 @@ highp vec4 metalRoughFunction(const in highp vec4 baseColor,
cLinear *= pow(2.0, exposure);
// Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1]
- highp vec3 cToneMapped = toneMap(cLinear);
+ vec3 cToneMapped = toneMap(cLinear);
// Apply gamma correction prior to display
- highp vec3 cGamma = gammaCorrect(cToneMapped);
+ vec3 cGamma = gammaCorrect(cToneMapped);
return vec4(cGamma, baseColor.a);
}
@@ -321,10 +321,10 @@ void main()
lights[2].linearAttenuation = 0.0;
lights[2].quadraticAttenuation = 0.0;
- highp vec3 color = vertColor;
- highp float alpha = vertAlpha;
+ vec3 color = vertColor;
+ float alpha = vertAlpha;
if (textureEnabled == 1) {
- highp vec4 textColor = texture2D(textureId, vertTexCoord);
+ vec4 textColor = texture2D(textureId, vertTexCoord);
color = textColor.rgb;
alpha = textColor.a;
}
@@ -335,7 +335,7 @@ void main()
}
color = pow(color, vec3(gamma));
- highp vec3 normal = vertNormal;
+ vec3 normal = vertNormal;
if (normalMapEnabled == 1) {
normal = texture2D(normalMapId, vertTexCoord).rgb;
normal = normalize(normal * 2.0 - 1.0);
@@ -345,17 +345,17 @@ void main()
// Green: Roughness
// Blue: Metallic
- highp float metalness = vertMetalness;
+ float metalness = vertMetalness;
if (metalnessMapEnabled == 1) {
metalness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b;
}
- highp float roughness = vertRoughness;
+ float roughness = vertRoughness;
if (roughnessMapEnabled == 1) {
roughness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g;
}
- highp float ambientOcclusion = 1.0;
+ float ambientOcclusion = 1.0;
if (ambientOcclusionMapEnabled == 1) {
ambientOcclusion = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r;
}
diff --git a/shaders/default.vert b/shaders/default.vert
index f0ccbf7c..e9e86e49 100644
--- a/shaders/default.vert
+++ b/shaders/default.vert
@@ -1,28 +1,28 @@
-attribute highp vec4 vertex;
-attribute highp vec3 normal;
-attribute highp vec3 color;
-attribute highp vec2 texCoord;
-attribute highp float metalness;
-attribute highp float roughness;
-attribute highp vec3 tangent;
-attribute highp float alpha;
-varying highp vec3 vert;
-varying highp vec3 vertRaw;
-varying highp vec3 vertNormal;
-varying highp vec3 vertColor;
-varying highp vec2 vertTexCoord;
-varying highp float vertMetalness;
-varying highp float vertRoughness;
-varying highp vec3 cameraPos;
-varying highp vec3 firstLightPos;
-varying highp vec3 secondLightPos;
-varying highp vec3 thirdLightPos;
-varying highp float vertAlpha;
-uniform highp mat4 projectionMatrix;
-uniform highp mat4 modelMatrix;
-uniform highp mat3 normalMatrix;
-uniform highp mat4 viewMatrix;
-uniform highp int normalMapEnabled;
+attribute vec4 vertex;
+attribute vec3 normal;
+attribute vec3 color;
+attribute vec2 texCoord;
+attribute float metalness;
+attribute float roughness;
+attribute vec3 tangent;
+attribute float alpha;
+varying vec3 vert;
+varying vec3 vertRaw;
+varying vec3 vertNormal;
+varying vec3 vertColor;
+varying vec2 vertTexCoord;
+varying float vertMetalness;
+varying float vertRoughness;
+varying vec3 cameraPos;
+varying vec3 firstLightPos;
+varying vec3 secondLightPos;
+varying vec3 thirdLightPos;
+varying float vertAlpha;
+uniform mat4 projectionMatrix;
+uniform mat4 modelMatrix;
+uniform mat3 normalMatrix;
+uniform mat4 viewMatrix;
+uniform int normalMapEnabled;
mat3 transpose(mat3 m)
{
diff --git a/src/ddsfile.cpp b/src/ddsfile.cpp
new file mode 100644
index 00000000..331ce473
--- /dev/null
+++ b/src/ddsfile.cpp
@@ -0,0 +1,523 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ddsfile.h"
+
+#ifndef _WIN32
+typedef quint32 DWORD;
+typedef quint32 UINT;
+#endif
+
+// DDS data struct copy from
+// https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide
+
+typedef struct {
+ DWORD dwSize;
+ DWORD dwFlags;
+ DWORD dwFourCC;
+ DWORD dwRGBBitCount;
+ DWORD dwRBitMask;
+ DWORD dwGBitMask;
+ DWORD dwBBitMask;
+ DWORD dwABitMask;
+} DDS_PIXELFORMAT;
+
+typedef enum {
+ DDSCAPS2_CUBEMAP = 0x200,
+ DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
+ DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
+ DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
+ DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
+ DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
+ DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
+ DDSCAPS2_VOLUME = 0x200000
+} DDS_CAPS2_FLAGS;
+
+typedef struct {
+ DWORD dwSize;
+ DWORD dwFlags;
+ DWORD dwHeight;
+ DWORD dwWidth;
+ DWORD dwPitchOrLinearSize;
+ DWORD dwDepth;
+ DWORD dwMipMapCount;
+ DWORD dwReserved1[11];
+ DDS_PIXELFORMAT ddspf;
+ DWORD dwCaps;
+ DWORD dwCaps2;
+ DWORD dwCaps3;
+ DWORD dwCaps4;
+ DWORD dwReserved2;
+} DDS_HEADER;
+
+typedef enum {
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32_TYPELESS,
+ DXGI_FORMAT_R32G32B32_FLOAT,
+ DXGI_FORMAT_R32G32B32_UINT,
+ DXGI_FORMAT_R32G32B32_SINT,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R32G32_TYPELESS,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_R32G8X24_TYPELESS,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ DXGI_FORMAT_X32_TYPELESS_G8X24_UINT,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R16G16_TYPELESS,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_R32_TYPELESS,
+ DXGI_FORMAT_D32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT,
+ DXGI_FORMAT_R8G8_TYPELESS,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_R16_TYPELESS,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_R8_TYPELESS,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_R1_UNORM,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_R8G8_B8G8_UNORM,
+ DXGI_FORMAT_G8R8_G8B8_UNORM,
+ DXGI_FORMAT_BC1_TYPELESS,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC2_TYPELESS,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_BC2_UNORM_SRGB,
+ DXGI_FORMAT_BC3_TYPELESS,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_BC3_UNORM_SRGB,
+ DXGI_FORMAT_BC4_TYPELESS,
+ DXGI_FORMAT_BC4_UNORM,
+ DXGI_FORMAT_BC4_SNORM,
+ DXGI_FORMAT_BC5_TYPELESS,
+ DXGI_FORMAT_BC5_UNORM,
+ DXGI_FORMAT_BC5_SNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_B8G8R8X8_TYPELESS,
+ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB,
+ DXGI_FORMAT_BC6H_TYPELESS,
+ DXGI_FORMAT_BC6H_UF16,
+ DXGI_FORMAT_BC6H_SF16,
+ DXGI_FORMAT_BC7_TYPELESS,
+ DXGI_FORMAT_BC7_UNORM,
+ DXGI_FORMAT_BC7_UNORM_SRGB,
+ DXGI_FORMAT_AYUV,
+ DXGI_FORMAT_Y410,
+ DXGI_FORMAT_Y416,
+ DXGI_FORMAT_NV12,
+ DXGI_FORMAT_P010,
+ DXGI_FORMAT_P016,
+ DXGI_FORMAT_420_OPAQUE,
+ DXGI_FORMAT_YUY2,
+ DXGI_FORMAT_Y210,
+ DXGI_FORMAT_Y216,
+ DXGI_FORMAT_NV11,
+ DXGI_FORMAT_AI44,
+ DXGI_FORMAT_IA44,
+ DXGI_FORMAT_P8,
+ DXGI_FORMAT_A8P8,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_P208,
+ DXGI_FORMAT_V208,
+ DXGI_FORMAT_V408,
+ DXGI_FORMAT_FORCE_UINT
+} DXGI_FORMAT;
+
+static const char *DxgiFormatToString(DXGI_FORMAT dxgiFormat)
+{
+ static const char *names[] = {
+ "DXGI_FORMAT_UNKNOWN",
+ "DXGI_FORMAT_R32G32B32A32_TYPELESS",
+ "DXGI_FORMAT_R32G32B32A32_FLOAT",
+ "DXGI_FORMAT_R32G32B32A32_UINT",
+ "DXGI_FORMAT_R32G32B32A32_SINT",
+ "DXGI_FORMAT_R32G32B32_TYPELESS",
+ "DXGI_FORMAT_R32G32B32_FLOAT",
+ "DXGI_FORMAT_R32G32B32_UINT",
+ "DXGI_FORMAT_R32G32B32_SINT",
+ "DXGI_FORMAT_R16G16B16A16_TYPELESS",
+ "DXGI_FORMAT_R16G16B16A16_FLOAT",
+ "DXGI_FORMAT_R16G16B16A16_UNORM",
+ "DXGI_FORMAT_R16G16B16A16_UINT",
+ "DXGI_FORMAT_R16G16B16A16_SNORM",
+ "DXGI_FORMAT_R16G16B16A16_SINT",
+ "DXGI_FORMAT_R32G32_TYPELESS",
+ "DXGI_FORMAT_R32G32_FLOAT",
+ "DXGI_FORMAT_R32G32_UINT",
+ "DXGI_FORMAT_R32G32_SINT",
+ "DXGI_FORMAT_R32G8X24_TYPELESS",
+ "DXGI_FORMAT_D32_FLOAT_S8X24_UINT",
+ "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS",
+ "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT",
+ "DXGI_FORMAT_R10G10B10A2_TYPELESS",
+ "DXGI_FORMAT_R10G10B10A2_UNORM",
+ "DXGI_FORMAT_R10G10B10A2_UINT",
+ "DXGI_FORMAT_R11G11B10_FLOAT",
+ "DXGI_FORMAT_R8G8B8A8_TYPELESS",
+ "DXGI_FORMAT_R8G8B8A8_UNORM",
+ "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB",
+ "DXGI_FORMAT_R8G8B8A8_UINT",
+ "DXGI_FORMAT_R8G8B8A8_SNORM",
+ "DXGI_FORMAT_R8G8B8A8_SINT",
+ "DXGI_FORMAT_R16G16_TYPELESS",
+ "DXGI_FORMAT_R16G16_FLOAT",
+ "DXGI_FORMAT_R16G16_UNORM",
+ "DXGI_FORMAT_R16G16_UINT",
+ "DXGI_FORMAT_R16G16_SNORM",
+ "DXGI_FORMAT_R16G16_SINT",
+ "DXGI_FORMAT_R32_TYPELESS",
+ "DXGI_FORMAT_D32_FLOAT",
+ "DXGI_FORMAT_R32_FLOAT",
+ "DXGI_FORMAT_R32_UINT",
+ "DXGI_FORMAT_R32_SINT",
+ "DXGI_FORMAT_R24G8_TYPELESS",
+ "DXGI_FORMAT_D24_UNORM_S8_UINT",
+ "DXGI_FORMAT_R24_UNORM_X8_TYPELESS",
+ "DXGI_FORMAT_X24_TYPELESS_G8_UINT",
+ "DXGI_FORMAT_R8G8_TYPELESS",
+ "DXGI_FORMAT_R8G8_UNORM",
+ "DXGI_FORMAT_R8G8_UINT",
+ "DXGI_FORMAT_R8G8_SNORM",
+ "DXGI_FORMAT_R8G8_SINT",
+ "DXGI_FORMAT_R16_TYPELESS",
+ "DXGI_FORMAT_R16_FLOAT",
+ "DXGI_FORMAT_D16_UNORM",
+ "DXGI_FORMAT_R16_UNORM",
+ "DXGI_FORMAT_R16_UINT",
+ "DXGI_FORMAT_R16_SNORM",
+ "DXGI_FORMAT_R16_SINT",
+ "DXGI_FORMAT_R8_TYPELESS",
+ "DXGI_FORMAT_R8_UNORM",
+ "DXGI_FORMAT_R8_UINT",
+ "DXGI_FORMAT_R8_SNORM",
+ "DXGI_FORMAT_R8_SINT",
+ "DXGI_FORMAT_A8_UNORM",
+ "DXGI_FORMAT_R1_UNORM",
+ "DXGI_FORMAT_R9G9B9E5_SHAREDEXP",
+ "DXGI_FORMAT_R8G8_B8G8_UNORM",
+ "DXGI_FORMAT_G8R8_G8B8_UNORM",
+ "DXGI_FORMAT_BC1_TYPELESS",
+ "DXGI_FORMAT_BC1_UNORM",
+ "DXGI_FORMAT_BC1_UNORM_SRGB",
+ "DXGI_FORMAT_BC2_TYPELESS",
+ "DXGI_FORMAT_BC2_UNORM",
+ "DXGI_FORMAT_BC2_UNORM_SRGB",
+ "DXGI_FORMAT_BC3_TYPELESS",
+ "DXGI_FORMAT_BC3_UNORM",
+ "DXGI_FORMAT_BC3_UNORM_SRGB",
+ "DXGI_FORMAT_BC4_TYPELESS",
+ "DXGI_FORMAT_BC4_UNORM",
+ "DXGI_FORMAT_BC4_SNORM",
+ "DXGI_FORMAT_BC5_TYPELESS",
+ "DXGI_FORMAT_BC5_UNORM",
+ "DXGI_FORMAT_BC5_SNORM",
+ "DXGI_FORMAT_B5G6R5_UNORM",
+ "DXGI_FORMAT_B5G5R5A1_UNORM",
+ "DXGI_FORMAT_B8G8R8A8_UNORM",
+ "DXGI_FORMAT_B8G8R8X8_UNORM",
+ "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM",
+ "DXGI_FORMAT_B8G8R8A8_TYPELESS",
+ "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB",
+ "DXGI_FORMAT_B8G8R8X8_TYPELESS",
+ "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB",
+ "DXGI_FORMAT_BC6H_TYPELESS",
+ "DXGI_FORMAT_BC6H_UF16",
+ "DXGI_FORMAT_BC6H_SF16",
+ "DXGI_FORMAT_BC7_TYPELESS",
+ "DXGI_FORMAT_BC7_UNORM",
+ "DXGI_FORMAT_BC7_UNORM_SRGB",
+ "DXGI_FORMAT_AYUV",
+ "DXGI_FORMAT_Y410",
+ "DXGI_FORMAT_Y416",
+ "DXGI_FORMAT_NV12",
+ "DXGI_FORMAT_P010",
+ "DXGI_FORMAT_P016",
+ "DXGI_FORMAT_420_OPAQUE",
+ "DXGI_FORMAT_YUY2",
+ "DXGI_FORMAT_Y210",
+ "DXGI_FORMAT_Y216",
+ "DXGI_FORMAT_NV11",
+ "DXGI_FORMAT_AI44",
+ "DXGI_FORMAT_IA44",
+ "DXGI_FORMAT_P8",
+ "DXGI_FORMAT_A8P8",
+ "DXGI_FORMAT_B4G4R4A4_UNORM",
+ "DXGI_FORMAT_P208",
+ "DXGI_FORMAT_V208",
+ "DXGI_FORMAT_V408",
+ "DXGI_FORMAT_FORCE_UINT",
+ };
+ int index = (int)dxgiFormat;
+ if (index >= 0 && index < sizeof(names) / sizeof(names[0]))
+ return names[index];
+ return "(Unknown)";
+}
+
+typedef enum {
+ D3D10_RESOURCE_DIMENSION_UNKNOWN,
+ D3D10_RESOURCE_DIMENSION_BUFFER,
+ D3D10_RESOURCE_DIMENSION_TEXTURE1D,
+ D3D10_RESOURCE_DIMENSION_TEXTURE2D,
+ D3D10_RESOURCE_DIMENSION_TEXTURE3D
+} D3D10_RESOURCE_DIMENSION;
+
+static const char *ResourceDimensionToString(D3D10_RESOURCE_DIMENSION resourceDimension)
+{
+ static const char *names[] = {
+ "D3D10_RESOURCE_DIMENSION_UNKNOWN",
+ "D3D10_RESOURCE_DIMENSION_BUFFER",
+ "D3D10_RESOURCE_DIMENSION_TEXTURE1D",
+ "D3D10_RESOURCE_DIMENSION_TEXTURE2D",
+ "D3D10_RESOURCE_DIMENSION_TEXTURE3D",
+ };
+ int index = (int)resourceDimension;
+ if (index >= 0 && index < sizeof(names) / sizeof(names[0]))
+ return names[index];
+ return "(Unknown)";
+}
+
+typedef enum {
+ D3D10_RESOURCE_MISC_GENERATE_MIPS,
+ D3D10_RESOURCE_MISC_SHARED,
+ D3D10_RESOURCE_MISC_TEXTURECUBE,
+ D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX,
+ D3D10_RESOURCE_MISC_GDI_COMPATIBLE
+} D3D10_RESOURCE_MISC_FLAG;
+
+static const char *MiscFlagToString(UINT miscFlag)
+{
+ static const char *names[] = {
+ "D3D10_RESOURCE_MISC_GENERATE_MIPS",
+ "D3D10_RESOURCE_MISC_SHARED",
+ "D3D10_RESOURCE_MISC_TEXTURECUBE",
+ "D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX",
+ "D3D10_RESOURCE_MISC_GDI_COMPATIBLE",
+ };
+ int index = (int)miscFlag;
+ if (index >= 0 && index < sizeof(names) / sizeof(names[0]))
+ return names[index];
+ return "(Unknown)";
+}
+
+typedef struct {
+ DXGI_FORMAT dxgiFormat;
+ D3D10_RESOURCE_DIMENSION resourceDimension;
+ UINT miscFlag;
+ UINT arraySize;
+ UINT miscFlags2;
+} DDS_HEADER_DXT10;
+
+typedef struct {
+ DWORD dwMagic;
+ DDS_HEADER header;
+ DDS_HEADER_DXT10 header10;
+} DDS_FILE_HEADER;
+
+DdsFileReader::DdsFileReader(const QString &filename) :
+ m_filename(filename)
+{
+}
+
+QOpenGLTexture *DdsFileReader::createOpenGLTexture()
+{
+ QFile file(m_filename);
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ qDebug() << "Open" << m_filename << "failed";
+ return nullptr;
+ }
+
+ DDS_FILE_HEADER fileHeader;
+ if (sizeof(fileHeader) != file.read((char *)&fileHeader, sizeof(fileHeader))) {
+ qDebug() << "Read DDS file hader failed";
+ return nullptr;
+ }
+
+ if (0x20534444 != qFromLittleEndian(&fileHeader.dwMagic)) {
+ qDebug() << "Not a DDS file";
+ return nullptr;
+ }
+
+ if (0x30315844 != qFromLittleEndian(&fileHeader.header.ddspf.dwFourCC)) {
+ qDebug() << "Unsupported DDS file, expected DX10 file";
+ return nullptr;
+ }
+
+ auto caps2 = qFromLittleEndian(&fileHeader.header.dwCaps2);
+ if (!(DDSCAPS2_CUBEMAP & caps2)) {
+ qDebug() << "Unsupported DDS file, expected CUBEMAP file";
+ return nullptr;
+ }
+
+ //qDebug() << "Start anyalize DDS file...";
+
+ int width = qFromLittleEndian(&fileHeader.header.dwWidth);
+ int height = qFromLittleEndian(&fileHeader.header.dwHeight);
+
+ //qDebug() << "DDS size:" << width << "X" << height;
+
+ //auto pitchOrLinearSize = qFromLittleEndian(&fileHeader.header.dwPitchOrLinearSize);
+ //qDebug() << "DDS pitch or linear size:" << pitchOrLinearSize;
+
+ auto arraySize = qFromLittleEndian(&fileHeader.header10.arraySize);
+ //qDebug() << "DDS array size:" << arraySize;
+
+ auto mipMapCount = qFromLittleEndian(&fileHeader.header.dwMipMapCount);
+ //qDebug() << "DDS mip map count:" << mipMapCount;
+
+ DXGI_FORMAT dxgiFormat = (DXGI_FORMAT)qFromLittleEndian(&fileHeader.header10.dxgiFormat);
+ //qDebug() << "DDS dxgi format:" << DxgiFormatToString(dxgiFormat);
+ //qDebug() << "DDS resource dimension:" << ResourceDimensionToString((D3D10_RESOURCE_DIMENSION)qFromLittleEndian(&fileHeader.header10.resourceDimension));
+ //qDebug() << "DDS misc flag:" << MiscFlagToString((UINT)qFromLittleEndian(&fileHeader.header10.miscFlag));
+
+ auto faces = 0;
+ if (DDSCAPS2_CUBEMAP_POSITIVEX & caps2) {
+ //qDebug() << "DDS found +x";
+ ++faces;
+ }
+ if (DDSCAPS2_CUBEMAP_NEGATIVEX & caps2) {
+ //qDebug() << "DDS found -x";
+ ++faces;
+ }
+ if (DDSCAPS2_CUBEMAP_POSITIVEY & caps2) {
+ //qDebug() << "DDS found +y";
+ ++faces;
+ }
+ if (DDSCAPS2_CUBEMAP_NEGATIVEY & caps2) {
+ //qDebug() << "DDS found -y";
+ ++faces;
+ }
+ if (DDSCAPS2_CUBEMAP_POSITIVEZ & caps2) {
+ //qDebug() << "DDS found +z";
+ ++faces;
+ }
+ if (DDSCAPS2_CUBEMAP_NEGATIVEZ & caps2) {
+ //qDebug() << "DDS found -z";
+ ++faces;
+ }
+
+ if (6 != faces) {
+ qDebug() << "Unsupported DDS file, expected six faces";
+ return nullptr;
+ }
+
+ if (1 != arraySize) {
+ qDebug() << "Unsupported DDS file, expected one layer";
+ return nullptr;
+ }
+
+ if (DXGI_FORMAT_R16G16B16A16_FLOAT != dxgiFormat) {
+ qDebug() << "Unsupported DDS file, expected dxgi format: DXGI_FORMAT_R16G16B16A16_FLOAT";
+ return nullptr;
+ }
+ int components = 8;
+ int oneFaceSize = 0;
+ auto calculateOneFaceSizeAtLevel = [=](int level) {
+ return qMax(width >> level, 1) * qMax(height >> level, 1) * components;
+ };
+ for (auto level = 0; level < mipMapCount; ++level) {
+ oneFaceSize += calculateOneFaceSizeAtLevel(level);
+ }
+ int totalSize = arraySize * faces * oneFaceSize;
+ const QByteArray data = file.read(totalSize);
+ if (data.size() < totalSize) {
+ qDebug() << "DDS file invalid, expected total size:" << totalSize << "read size:" << data.size();
+ return nullptr;
+ }
+
+ int depth = 1;
+
+ QOpenGLTexture* texture = new QOpenGLTexture(QOpenGLTexture::TargetCubeMap);
+ texture->setFormat(QOpenGLTexture::RGBA16F);
+ texture->setSize(width, height, depth);
+ texture->setAutoMipMapGenerationEnabled(false);
+ texture->setMipBaseLevel(0);
+ texture->setMipMaxLevel(mipMapCount - 1);
+ texture->setMipLevels(mipMapCount);
+
+ if (!texture->create()) {
+ qDebug() << "QOpenGLTexture::create failed";
+ delete texture;
+ return nullptr;
+ }
+
+ texture->allocateStorage();
+ if (!texture->isStorageAllocated()) {
+ qDebug() << "QOpenGLTexture::isStorageAllocated false";
+ delete texture;
+ return nullptr;
+ }
+
+ uint64_t dataOffset = 0;
+ for (int layer = 0; layer < arraySize; ++layer) {
+ for (int face = 0; face < faces; ++face) {
+ for (int level = 0; level < mipMapCount; ++level) {
+ QOpenGLPixelTransferOptions uploadOptions;
+ uploadOptions.setAlignment(1);
+ texture->setData(level,
+ layer,
+ static_cast(QOpenGLTexture::CubeMapPositiveX + face),
+ QOpenGLTexture::RGBA,
+ QOpenGLTexture::Float16,
+ data.constData() + dataOffset,
+ &uploadOptions);
+ dataOffset += calculateOneFaceSizeAtLevel(level);
+ }
+ }
+ }
+
+ return texture;
+}
\ No newline at end of file
diff --git a/src/ddsfile.h b/src/ddsfile.h
new file mode 100644
index 00000000..ad916fae
--- /dev/null
+++ b/src/ddsfile.h
@@ -0,0 +1,15 @@
+#ifndef DUST3D_DDS_FILE_H
+#define DUST3D_DDS_FILE_H
+#include
+#include
+
+class DdsFileReader
+{
+public:
+ DdsFileReader(const QString &filename);
+ QOpenGLTexture *createOpenGLTexture();
+private:
+ QString m_filename;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/document.cpp b/src/document.cpp
index 877241ae..44cc65ec 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -7,7 +7,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include "document.h"
@@ -57,7 +57,6 @@ Document::Document() :
m_postProcessedOutcome(new Outcome),
m_resultTextureMesh(nullptr),
m_textureImageUpdateVersion(0),
- m_sharedContextWidget(nullptr),
m_allPositionRelatedLocksEnabled(true),
m_smoothNormal(!Preferences::instance().flatShading()),
m_rigGenerator(nullptr),
@@ -3311,11 +3310,6 @@ void Document::checkExportReadyState()
emit exportReady();
}
-void Document::setSharedContextWidget(QOpenGLWidget *sharedContextWidget)
-{
- m_sharedContextWidget = sharedContextWidget;
-}
-
void Document::collectComponentDescendantParts(QUuid componentId, std::vector &partIds) const
{
const Component *component = findComponent(componentId);
diff --git a/src/document.h b/src/document.h
index 780dbf58..bba6df61 100644
--- a/src/document.h
+++ b/src/document.h
@@ -9,7 +9,6 @@
#include
#include
#include
-#include
#include
#include "snapshot.h"
#include "meshloader.h"
@@ -577,7 +576,6 @@ public:
const std::vector *resultRigBones() const;
const std::map *resultRigWeights() const;
void updateTurnaround(const QImage &image);
- void setSharedContextWidget(QOpenGLWidget *sharedContextWidget);
bool hasPastableMaterialsInClipboard() const;
bool hasPastablePosesInClipboard() const;
bool hasPastableMotionsInClipboard() const;
@@ -781,7 +779,6 @@ private: // need initialize
Outcome *m_postProcessedOutcome;
MeshLoader *m_resultTextureMesh;
unsigned long long m_textureImageUpdateVersion;
- QOpenGLWidget *m_sharedContextWidget;
QUuid m_currentCanvasComponentId;
bool m_allPositionRelatedLocksEnabled;
bool m_smoothNormal;
diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp
index 888a63d2..7e1c66ed 100644
--- a/src/documentwindow.cpp
+++ b/src/documentwindow.cpp
@@ -6,7 +6,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -311,6 +311,7 @@ DocumentWindow::DocumentWindow() :
m_modelRenderWidget->move(DocumentWindow::m_modelRenderWidgetInitialX, DocumentWindow::m_modelRenderWidgetInitialY);
m_modelRenderWidget->setMousePickRadius(m_document->mousePickRadius());
m_modelRenderWidget->toggleWireframe();
+ m_modelRenderWidget->enableEnvironmentLight();
connect(m_modelRenderWidget, &ModelWidget::mouseRayChanged, m_document,
[=](const QVector3D &nearPosition, const QVector3D &farPosition) {
@@ -343,8 +344,6 @@ DocumentWindow::DocumentWindow() :
m_graphicsWidget->setModelWidget(m_modelRenderWidget);
containerWidget->setModelWidget(m_modelRenderWidget);
- m_document->setSharedContextWidget(m_modelRenderWidget);
-
setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East);
QDockWidget *partTreeDocker = new QDockWidget(tr("Parts"), this);
diff --git a/src/fbxfile.cpp b/src/fbxfile.cpp
index 46353af5..3a54630c 100644
--- a/src/fbxfile.cpp
+++ b/src/fbxfile.cpp
@@ -2,7 +2,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include "fbxfile.h"
diff --git a/src/glbfile.cpp b/src/glbfile.cpp
index 2381a8cb..9044fd65 100644
--- a/src/glbfile.cpp
+++ b/src/glbfile.cpp
@@ -4,7 +4,7 @@
#include
#include
#include
-#include
+#include
#include "glbfile.h"
#include "version.h"
#include "util.h"
diff --git a/src/imageforever.cpp b/src/imageforever.cpp
index 57e67c52..efa88a16 100644
--- a/src/imageforever.cpp
+++ b/src/imageforever.cpp
@@ -1,7 +1,7 @@
#include