Fix IBL shader

Implement DDS cubemap file reader to load the Cedar Bridge environment
cubemap file, and render IBL on core profile.
master
huxingyi 2020-03-18 23:47:09 +09:30
parent 81a95d6cad
commit c84bb14ada
26 changed files with 1047 additions and 296 deletions

View File

@ -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, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
</pre>
<h1>Greg Zaal</h1>
<pre>
https://hdrihaven.com/hdri/?h=cedar_bridge
</pre> </pre>

View File

@ -505,6 +505,9 @@ HEADERS += src/projectfacestonodes.h
SOURCES += src/simulateclothmeshes.cpp SOURCES += src/simulateclothmeshes.cpp
HEADERS += src/simulateclothmeshes.h HEADERS += src/simulateclothmeshes.h
SOURCES += src/ddsfile.cpp
HEADERS += src/ddsfile.h
SOURCES += src/main.cpp SOURCES += src/main.cpp
HEADERS += src/version.h HEADERS += src/version.h

View File

@ -23,6 +23,8 @@
<file>resources/heptagon.png</file> <file>resources/heptagon.png</file>
<file>resources/userdefined.png</file> <file>resources/userdefined.png</file>
<file>resources/checkuv.png</file> <file>resources/checkuv.png</file>
<file>resources/cedar_bridge_irradiance.dds</file>
<file>resources/cedar_bridge_specular.dds</file>
<file>shaders/default.vert</file> <file>shaders/default.vert</file>
<file>shaders/default.frag</file> <file>shaders/default.frag</file>
<file>shaders/default.core.vert</file> <file>shaders/default.core.vert</file>

Binary file not shown.

Binary file not shown.

View File

@ -53,35 +53,39 @@
// https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag // https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag
// Exposure correction // Exposure correction
highp float exposure; float exposure;
// Gamma correction // Gamma correction
highp float gamma; float gamma;
in highp vec3 vert; in vec3 vert;
in highp vec3 vertRaw; in vec3 vertRaw;
in highp vec3 vertNormal; in vec3 vertNormal;
in highp vec3 vertColor; in vec3 vertColor;
in highp vec2 vertTexCoord; in vec2 vertTexCoord;
in highp float vertMetalness; in float vertMetalness;
in highp float vertRoughness; in float vertRoughness;
in highp vec3 cameraPos; in vec3 cameraPos;
in highp vec3 firstLightPos; in vec3 firstLightPos;
in highp vec3 secondLightPos; in vec3 secondLightPos;
in highp vec3 thirdLightPos; in vec3 thirdLightPos;
in highp float vertAlpha; in float vertAlpha;
out highp vec4 fragColor; out vec4 fragColor;
uniform highp vec3 lightPos; uniform vec3 lightPos;
uniform highp sampler2D textureId; uniform sampler2D textureId;
uniform highp int textureEnabled; uniform int textureEnabled;
uniform highp sampler2D normalMapId; uniform sampler2D normalMapId;
uniform highp int normalMapEnabled; uniform int normalMapEnabled;
uniform highp sampler2D metalnessRoughnessAmbientOcclusionMapId; uniform sampler2D metalnessRoughnessAmbientOcclusionMapId;
uniform highp int metalnessMapEnabled; uniform int metalnessMapEnabled;
uniform highp int roughnessMapEnabled; uniform int roughnessMapEnabled;
uniform highp int ambientOcclusionMapEnabled; uniform int ambientOcclusionMapEnabled;
uniform highp int mousePickEnabled; uniform int mousePickEnabled;
uniform highp vec3 mousePickTargetPosition; uniform vec3 mousePickTargetPosition;
uniform highp float mousePickRadius; uniform float mousePickRadius;
uniform samplerCube environmentIrradianceMapId;
uniform int environmentIrradianceMapEnabled;
uniform samplerCube environmentSpecularMapId;
uniform int environmentSpecularMapEnabled;
const int MAX_LIGHTS = 8; const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0; const int TYPE_POINT = 0;
@ -89,51 +93,88 @@ const int TYPE_DIRECTIONAL = 1;
const int TYPE_SPOT = 2; const int TYPE_SPOT = 2;
struct Light { struct Light {
int type; int type;
highp vec3 position; vec3 position;
highp vec3 color; vec3 color;
highp float intensity; float intensity;
highp vec3 direction; vec3 direction;
highp float constantAttenuation; float constantAttenuation;
highp float linearAttenuation; float linearAttenuation;
highp float quadraticAttenuation; float quadraticAttenuation;
highp float cutOffAngle; float cutOffAngle;
}; };
int lightCount; int lightCount;
Light lights[MAX_LIGHTS]; 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 // As per page 14 of
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf // 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 // we remap the roughness to give a more perceptually linear response
// of "bluriness" as a function of the roughness specified by the user. // of "bluriness" as a function of the roughness specified by the user.
// r = roughness^2 // r = roughness^2
highp float maxSpecPower; float maxSpecPower;
highp float minRoughness; float minRoughness;
maxSpecPower = 999999.0; maxSpecPower = 999999.0;
minRoughness = sqrt(2.0 / (maxSpecPower + 2.0)); minRoughness = sqrt(2.0 / (maxSpecPower + 2.0));
return max(roughness * roughness, minRoughness); 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 // Blinn-Phong approximation - see
// http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html // 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); 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 // Calculate the Fresnel effect value
highp vec3 f = color; vec3 f = color;
highp vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0); vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
return clamp(F, f, vec3(1.0)); return clamp(F, f, vec3(1.0));
} }
highp float geometricModel(const in highp float lDotN, float geometricModel(const in float lDotN,
const in highp float vDotN, const in float vDotN,
const in highp vec3 h) const in vec3 h)
{ {
// Implicit geometric model (equal to denominator in specular model). // Implicit geometric model (equal to denominator in specular model).
// This currently assumes that there is no attenuation by geometric shadowing or // 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; return lDotN * vDotN;
} }
highp vec3 specularModel(const in highp vec3 F0, vec3 specularModel(const in vec3 F0,
const in highp float sDotH, const in float sDotH,
const in highp float sDotN, const in float sDotN,
const in highp float vDotN, const in float vDotN,
const in highp vec3 n, const in vec3 n,
const in highp vec3 h) const in vec3 h)
{ {
// Clamp sDotN and vDotN to small positive value to prevent the // Clamp sDotN and vDotN to small positive value to prevent the
// denominator in the reflection equation going to infinity. Balance this // denominator in the reflection equation going to infinity. Balance this
// by using the clamped values in the geometric factor function to // by using the clamped values in the geometric factor function to
// avoid ugly seams in the specular lighting. // avoid ugly seams in the specular lighting.
highp float sDotNPrime = max(sDotN, 0.001); float sDotNPrime = max(sDotN, 0.001);
highp float vDotNPrime = max(vDotN, 0.001); float vDotNPrime = max(vDotN, 0.001);
highp vec3 F = fresnelFactor(F0, sDotH); vec3 F = fresnelFactor(F0, sDotH);
highp float G = geometricModel(sDotNPrime, vDotNPrime, h); 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)); return clamp(cSpec, vec3(0.0), vec3(1.0));
} }
highp vec3 pbrModel(const in int lightIndex, vec3 pbrModel(const in int lightIndex,
const in highp vec3 wPosition, const in vec3 wPosition,
const in highp vec3 wNormal, const in vec3 wNormal,
const in highp vec3 wView, const in vec3 wView,
const in highp vec3 baseColor, const in vec3 baseColor,
const in highp float metalness, const in float metalness,
const in highp float alpha, const in float alpha,
const in highp float ambientOcclusion) const in float ambientOcclusion)
{ {
// Calculate some useful quantities // Calculate some useful quantities
highp vec3 n = wNormal; vec3 n = wNormal;
highp vec3 s = vec3(0.0); vec3 s = vec3(0.0);
highp vec3 v = wView; vec3 v = wView;
highp vec3 h = vec3(0.0); vec3 h = vec3(0.0);
highp float vDotN = dot(v, n); float vDotN = dot(v, n);
highp float sDotN = 0.0; float sDotN = 0.0;
highp float sDotH = 0.0; float sDotH = 0.0;
highp float att = 1.0; float att = 1.0;
if (lights[lightIndex].type != TYPE_DIRECTIONAL) { if (lights[lightIndex].type != TYPE_DIRECTIONAL) {
// Point and Spot lights // Point and Spot lights
highp vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition; vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition;
s = normalize(sUnnormalized); s = normalize(sUnnormalized);
// Calculate the attenuation factor // Calculate the attenuation factor
@ -193,7 +234,7 @@ highp vec3 pbrModel(const in int lightIndex,
if (lights[lightIndex].constantAttenuation != 0.0 if (lights[lightIndex].constantAttenuation != 0.0
|| lights[lightIndex].linearAttenuation != 0.0 || lights[lightIndex].linearAttenuation != 0.0
|| lights[lightIndex].quadraticAttenuation != 0.0) { || lights[lightIndex].quadraticAttenuation != 0.0) {
highp float dist = length(sUnnormalized); float dist = length(sUnnormalized);
att = 1.0 / (lights[lightIndex].constantAttenuation + att = 1.0 / (lights[lightIndex].constantAttenuation +
lights[lightIndex].linearAttenuation * dist + lights[lightIndex].linearAttenuation * dist +
lights[lightIndex].quadraticAttenuation * dist * dist); lights[lightIndex].quadraticAttenuation * dist * dist);
@ -217,22 +258,22 @@ highp vec3 pbrModel(const in int lightIndex,
sDotH = dot(s, h); sDotH = dot(s, h);
// Calculate diffuse component // Calculate diffuse component
highp vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color; vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
highp vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159; vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
// Calculate specular component // Calculate specular component
highp vec3 dielectricColor = vec3(0.04); vec3 dielectricColor = vec3(0.04);
highp vec3 F0 = mix(dielectricColor, baseColor, metalness); vec3 F0 = mix(dielectricColor, baseColor, metalness);
highp vec3 specularFactor = vec3(0.0); vec3 specularFactor = vec3(0.0);
if (sDotN > 0.0) { if (sDotN > 0.0) {
specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h); specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h);
specularFactor *= normalDistribution(n, h, alpha); specularFactor *= normalDistribution(n, h, alpha);
} }
highp vec3 specularColor = lights[lightIndex].color; vec3 specularColor = lights[lightIndex].color;
highp vec3 specular = specularColor * specularFactor; vec3 specular = specularColor * specularFactor;
// Blend between diffuse and specular to conserver energy // 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 // Reduce by ambient occlusion amount
color *= ambientOcclusion; color *= ambientOcclusion;
@ -240,29 +281,99 @@ highp vec3 pbrModel(const in int lightIndex,
return color; 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)); 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)); return pow(color, vec3(1.0 / gamma));
} }
highp vec4 metalRoughFunction(const in highp vec4 baseColor, vec4 metalRoughFunction(const in vec4 baseColor,
const in highp float metalness, const in float metalness,
const in highp float roughness, const in float roughness,
const in highp float ambientOcclusion, const in float ambientOcclusion,
const in highp vec3 worldPosition, const in vec3 worldPosition,
const in highp vec3 worldView, const in vec3 worldView,
const in highp vec3 worldNormal) const in vec3 worldNormal)
{ {
highp vec3 cLinear = vec3(0.0); vec3 cLinear = vec3(0.0);
// Remap roughness for a perceptually more linear correspondence // 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) { for (int i = 0; i < lightCount; ++i) {
cLinear += pbrModel(i, cLinear += pbrModel(i,
worldPosition, worldPosition,
@ -278,10 +389,10 @@ highp vec4 metalRoughFunction(const in highp vec4 baseColor,
cLinear *= pow(2.0, exposure); cLinear *= pow(2.0, exposure);
// Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1] // 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 // Apply gamma correction prior to display
highp vec3 cGamma = gammaCorrect(cToneMapped); vec3 cGamma = gammaCorrect(cToneMapped);
return vec4(cGamma, baseColor.a); return vec4(cGamma, baseColor.a);
} }
@ -323,10 +434,10 @@ void main()
lights[2].linearAttenuation = 0.0; lights[2].linearAttenuation = 0.0;
lights[2].quadraticAttenuation = 0.0; lights[2].quadraticAttenuation = 0.0;
highp vec3 color = vertColor; vec3 color = vertColor;
highp float alpha = vertAlpha; float alpha = vertAlpha;
if (textureEnabled == 1) { if (textureEnabled == 1) {
highp vec4 textColor = texture(textureId, vertTexCoord); vec4 textColor = texture(textureId, vertTexCoord);
color = textColor.rgb; color = textColor.rgb;
alpha = textColor.a; alpha = textColor.a;
} }
@ -337,7 +448,7 @@ void main()
} }
color = pow(color, vec3(gamma)); color = pow(color, vec3(gamma));
highp vec3 normal = vertNormal; vec3 normal = vertNormal;
if (normalMapEnabled == 1) { if (normalMapEnabled == 1) {
normal = texture(normalMapId, vertTexCoord).rgb; normal = texture(normalMapId, vertTexCoord).rgb;
normal = normalize(normal * 2.0 - 1.0); normal = normalize(normal * 2.0 - 1.0);
@ -347,23 +458,25 @@ void main()
// Green: Roughness // Green: Roughness
// Blue: Metallic // Blue: Metallic
highp float metalness = vertMetalness; float metalness = vertMetalness;
if (metalnessMapEnabled == 1) { if (metalnessMapEnabled == 1) {
metalness = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b; metalness = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b;
} }
highp float roughness = vertRoughness; float roughness = vertRoughness;
if (roughnessMapEnabled == 1) { if (roughnessMapEnabled == 1) {
roughness = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g; roughness = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g;
} }
highp float ambientOcclusion = 1.0; float ambientOcclusion = 1.0;
if (ambientOcclusionMapEnabled == 1) { if (ambientOcclusionMapEnabled == 1) {
ambientOcclusion = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r; ambientOcclusion = texture(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r;
} }
roughness = min(0.99, roughness); if (environmentIrradianceMapEnabled != 1) {
metalness = min(0.99, metalness); roughness = min(0.99, roughness);
metalness = min(0.99, metalness);
}
fragColor = metalRoughFunction(vec4(color, alpha), fragColor = metalRoughFunction(vec4(color, alpha),
metalness, metalness,

View File

@ -1,29 +1,29 @@
#version 330 #version 330
layout(location = 0) in highp vec4 vertex; layout(location = 0) in vec4 vertex;
layout(location = 1) in highp vec3 normal; layout(location = 1) in vec3 normal;
layout(location = 2) in highp vec3 color; layout(location = 2) in vec3 color;
layout(location = 3) in highp vec2 texCoord; layout(location = 3) in vec2 texCoord;
layout(location = 4) in highp float metalness; layout(location = 4) in float metalness;
layout(location = 5) in highp float roughness; layout(location = 5) in float roughness;
layout(location = 6) in highp vec3 tangent; layout(location = 6) in vec3 tangent;
layout(location = 7) in highp float alpha; layout(location = 7) in float alpha;
out highp vec3 vert; out vec3 vert;
out highp vec3 vertRaw; out vec3 vertRaw;
out highp vec3 vertNormal; out vec3 vertNormal;
out highp vec3 vertColor; out vec3 vertColor;
out highp vec2 vertTexCoord; out vec2 vertTexCoord;
out highp float vertMetalness; out float vertMetalness;
out highp float vertRoughness; out float vertRoughness;
out highp vec3 cameraPos; out vec3 cameraPos;
out highp vec3 firstLightPos; out vec3 firstLightPos;
out highp vec3 secondLightPos; out vec3 secondLightPos;
out highp vec3 thirdLightPos; out vec3 thirdLightPos;
out highp float vertAlpha; out float vertAlpha;
uniform highp mat4 projectionMatrix; uniform mat4 projectionMatrix;
uniform highp mat4 modelMatrix; uniform mat4 modelMatrix;
uniform highp mat3 normalMatrix; uniform mat3 normalMatrix;
uniform highp mat4 viewMatrix; uniform mat4 viewMatrix;
uniform highp int normalMapEnabled; uniform int normalMapEnabled;
mat3 transpose(mat3 m) mat3 transpose(mat3 m)
{ {

View File

@ -52,34 +52,34 @@
// https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag // https://github.com/qt/qt3d/blob/5.11/src/extras/shaders/gl3/metalrough.inc.frag
// Exposure correction // Exposure correction
highp float exposure; float exposure;
// Gamma correction // Gamma correction
highp float gamma; float gamma;
varying highp vec3 vert; varying vec3 vert;
varying highp vec3 vertRaw; varying vec3 vertRaw;
varying highp vec3 vertNormal; varying vec3 vertNormal;
varying highp vec3 vertColor; varying vec3 vertColor;
varying highp vec2 vertTexCoord; varying vec2 vertTexCoord;
varying highp float vertMetalness; varying float vertMetalness;
varying highp float vertRoughness; varying float vertRoughness;
varying highp vec3 cameraPos; varying vec3 cameraPos;
varying highp vec3 firstLightPos; varying vec3 firstLightPos;
varying highp vec3 secondLightPos; varying vec3 secondLightPos;
varying highp vec3 thirdLightPos; varying vec3 thirdLightPos;
varying highp float vertAlpha; varying float vertAlpha;
uniform highp vec3 lightPos; uniform vec3 lightPos;
uniform highp sampler2D textureId; uniform sampler2D textureId;
uniform highp int textureEnabled; uniform int textureEnabled;
uniform highp sampler2D normalMapId; uniform sampler2D normalMapId;
uniform highp int normalMapEnabled; uniform int normalMapEnabled;
uniform highp sampler2D metalnessRoughnessAmbientOcclusionMapId; uniform sampler2D metalnessRoughnessAmbientOcclusionMapId;
uniform highp int metalnessMapEnabled; uniform int metalnessMapEnabled;
uniform highp int roughnessMapEnabled; uniform int roughnessMapEnabled;
uniform highp int ambientOcclusionMapEnabled; uniform int ambientOcclusionMapEnabled;
uniform highp int mousePickEnabled; uniform int mousePickEnabled;
uniform highp vec3 mousePickTargetPosition; uniform vec3 mousePickTargetPosition;
uniform highp float mousePickRadius; uniform float mousePickRadius;
const int MAX_LIGHTS = 8; const int MAX_LIGHTS = 8;
const int TYPE_POINT = 0; const int TYPE_POINT = 0;
@ -87,51 +87,51 @@ const int TYPE_DIRECTIONAL = 1;
const int TYPE_SPOT = 2; const int TYPE_SPOT = 2;
struct Light { struct Light {
int type; int type;
highp vec3 position; vec3 position;
highp vec3 color; vec3 color;
highp float intensity; float intensity;
highp vec3 direction; vec3 direction;
highp float constantAttenuation; float constantAttenuation;
highp float linearAttenuation; float linearAttenuation;
highp float quadraticAttenuation; float quadraticAttenuation;
highp float cutOffAngle; float cutOffAngle;
}; };
int lightCount; int lightCount;
Light lights[MAX_LIGHTS]; Light lights[MAX_LIGHTS];
highp float remapRoughness(const in highp float roughness) float remapRoughness(const in float roughness)
{ {
// As per page 14 of // As per page 14 of
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf // 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 // we remap the roughness to give a more perceptually linear response
// of "bluriness" as a function of the roughness specified by the user. // of "bluriness" as a function of the roughness specified by the user.
// r = roughness^2 // r = roughness^2
highp float maxSpecPower; float maxSpecPower;
highp float minRoughness; float minRoughness;
maxSpecPower = 999999.0; maxSpecPower = 999999.0;
minRoughness = sqrt(2.0 / (maxSpecPower + 2.0)); minRoughness = sqrt(2.0 / (maxSpecPower + 2.0));
return max(roughness * roughness, minRoughness); 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 // Blinn-Phong approximation - see
// http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html // 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); 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 // Calculate the Fresnel effect value
highp vec3 f = color; vec3 f = color;
highp vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0); vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0);
return clamp(F, f, vec3(1.0)); return clamp(F, f, vec3(1.0));
} }
highp float geometricModel(const in highp float lDotN, float geometricModel(const in float lDotN,
const in highp float vDotN, const in float vDotN,
const in highp vec3 h) const in vec3 h)
{ {
// Implicit geometric model (equal to denominator in specular model). // Implicit geometric model (equal to denominator in specular model).
// This currently assumes that there is no attenuation by geometric shadowing or // 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; return lDotN * vDotN;
} }
highp vec3 specularModel(const in highp vec3 F0, vec3 specularModel(const in vec3 F0,
const in highp float sDotH, const in float sDotH,
const in highp float sDotN, const in float sDotN,
const in highp float vDotN, const in float vDotN,
const in highp vec3 n, const in vec3 n,
const in highp vec3 h) const in vec3 h)
{ {
// Clamp sDotN and vDotN to small positive value to prevent the // Clamp sDotN and vDotN to small positive value to prevent the
// denominator in the reflection equation going to infinity. Balance this // denominator in the reflection equation going to infinity. Balance this
// by using the clamped values in the geometric factor function to // by using the clamped values in the geometric factor function to
// avoid ugly seams in the specular lighting. // avoid ugly seams in the specular lighting.
highp float sDotNPrime = max(sDotN, 0.001); float sDotNPrime = max(sDotN, 0.001);
highp float vDotNPrime = max(vDotN, 0.001); float vDotNPrime = max(vDotN, 0.001);
highp vec3 F = fresnelFactor(F0, sDotH); vec3 F = fresnelFactor(F0, sDotH);
highp float G = geometricModel(sDotNPrime, vDotNPrime, h); 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)); return clamp(cSpec, vec3(0.0), vec3(1.0));
} }
highp vec3 pbrModel(const in int lightIndex, vec3 pbrModel(const in int lightIndex,
const in highp vec3 wPosition, const in vec3 wPosition,
const in highp vec3 wNormal, const in vec3 wNormal,
const in highp vec3 wView, const in vec3 wView,
const in highp vec3 baseColor, const in vec3 baseColor,
const in highp float metalness, const in float metalness,
const in highp float alpha, const in float alpha,
const in highp float ambientOcclusion) const in float ambientOcclusion)
{ {
// Calculate some useful quantities // Calculate some useful quantities
highp vec3 n = wNormal; vec3 n = wNormal;
highp vec3 s = vec3(0.0); vec3 s = vec3(0.0);
highp vec3 v = wView; vec3 v = wView;
highp vec3 h = vec3(0.0); vec3 h = vec3(0.0);
highp float vDotN = dot(v, n); float vDotN = dot(v, n);
highp float sDotN = 0.0; float sDotN = 0.0;
highp float sDotH = 0.0; float sDotH = 0.0;
highp float att = 1.0; float att = 1.0;
if (lights[lightIndex].type != TYPE_DIRECTIONAL) { if (lights[lightIndex].type != TYPE_DIRECTIONAL) {
// Point and Spot lights // Point and Spot lights
highp vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition; vec3 sUnnormalized = vec3(lights[lightIndex].position) - wPosition;
s = normalize(sUnnormalized); s = normalize(sUnnormalized);
// Calculate the attenuation factor // Calculate the attenuation factor
@ -191,7 +191,7 @@ highp vec3 pbrModel(const in int lightIndex,
if (lights[lightIndex].constantAttenuation != 0.0 if (lights[lightIndex].constantAttenuation != 0.0
|| lights[lightIndex].linearAttenuation != 0.0 || lights[lightIndex].linearAttenuation != 0.0
|| lights[lightIndex].quadraticAttenuation != 0.0) { || lights[lightIndex].quadraticAttenuation != 0.0) {
highp float dist = length(sUnnormalized); float dist = length(sUnnormalized);
att = 1.0 / (lights[lightIndex].constantAttenuation + att = 1.0 / (lights[lightIndex].constantAttenuation +
lights[lightIndex].linearAttenuation * dist + lights[lightIndex].linearAttenuation * dist +
lights[lightIndex].quadraticAttenuation * dist * dist); lights[lightIndex].quadraticAttenuation * dist * dist);
@ -215,22 +215,22 @@ highp vec3 pbrModel(const in int lightIndex,
sDotH = dot(s, h); sDotH = dot(s, h);
// Calculate diffuse component // Calculate diffuse component
highp vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color; vec3 diffuseColor = (1.0 - metalness) * baseColor * lights[lightIndex].color;
highp vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159; vec3 diffuse = diffuseColor * max(sDotN, 0.0) / 3.14159;
// Calculate specular component // Calculate specular component
highp vec3 dielectricColor = vec3(0.04); vec3 dielectricColor = vec3(0.04);
highp vec3 F0 = mix(dielectricColor, baseColor, metalness); vec3 F0 = mix(dielectricColor, baseColor, metalness);
highp vec3 specularFactor = vec3(0.0); vec3 specularFactor = vec3(0.0);
if (sDotN > 0.0) { if (sDotN > 0.0) {
specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h); specularFactor = specularModel(F0, sDotH, sDotN, vDotN, n, h);
specularFactor *= normalDistribution(n, h, alpha); specularFactor *= normalDistribution(n, h, alpha);
} }
highp vec3 specularColor = lights[lightIndex].color; vec3 specularColor = lights[lightIndex].color;
highp vec3 specular = specularColor * specularFactor; vec3 specular = specularColor * specularFactor;
// Blend between diffuse and specular to conserver energy // 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 // Reduce by ambient occlusion amount
color *= ambientOcclusion; color *= ambientOcclusion;
@ -238,28 +238,28 @@ highp vec3 pbrModel(const in int lightIndex,
return color; return color;
} }
highp vec3 toneMap(const in highp vec3 c) vec3 toneMap(const in vec3 c)
{ {
return c / (c + vec3(1.0)); 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)); return pow(color, vec3(1.0 / gamma));
} }
highp vec4 metalRoughFunction(const in highp vec4 baseColor, vec4 metalRoughFunction(const in vec4 baseColor,
const in highp float metalness, const in float metalness,
const in highp float roughness, const in float roughness,
const in highp float ambientOcclusion, const in float ambientOcclusion,
const in highp vec3 worldPosition, const in vec3 worldPosition,
const in highp vec3 worldView, const in vec3 worldView,
const in highp vec3 worldNormal) const in vec3 worldNormal)
{ {
highp vec3 cLinear = vec3(0.0); vec3 cLinear = vec3(0.0);
// Remap roughness for a perceptually more linear correspondence // Remap roughness for a perceptually more linear correspondence
highp float alpha = remapRoughness(roughness); float alpha = remapRoughness(roughness);
for (int i = 0; i < lightCount; ++i) { for (int i = 0; i < lightCount; ++i) {
cLinear += pbrModel(i, cLinear += pbrModel(i,
@ -276,10 +276,10 @@ highp vec4 metalRoughFunction(const in highp vec4 baseColor,
cLinear *= pow(2.0, exposure); cLinear *= pow(2.0, exposure);
// Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1] // 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 // Apply gamma correction prior to display
highp vec3 cGamma = gammaCorrect(cToneMapped); vec3 cGamma = gammaCorrect(cToneMapped);
return vec4(cGamma, baseColor.a); return vec4(cGamma, baseColor.a);
} }
@ -321,10 +321,10 @@ void main()
lights[2].linearAttenuation = 0.0; lights[2].linearAttenuation = 0.0;
lights[2].quadraticAttenuation = 0.0; lights[2].quadraticAttenuation = 0.0;
highp vec3 color = vertColor; vec3 color = vertColor;
highp float alpha = vertAlpha; float alpha = vertAlpha;
if (textureEnabled == 1) { if (textureEnabled == 1) {
highp vec4 textColor = texture2D(textureId, vertTexCoord); vec4 textColor = texture2D(textureId, vertTexCoord);
color = textColor.rgb; color = textColor.rgb;
alpha = textColor.a; alpha = textColor.a;
} }
@ -335,7 +335,7 @@ void main()
} }
color = pow(color, vec3(gamma)); color = pow(color, vec3(gamma));
highp vec3 normal = vertNormal; vec3 normal = vertNormal;
if (normalMapEnabled == 1) { if (normalMapEnabled == 1) {
normal = texture2D(normalMapId, vertTexCoord).rgb; normal = texture2D(normalMapId, vertTexCoord).rgb;
normal = normalize(normal * 2.0 - 1.0); normal = normalize(normal * 2.0 - 1.0);
@ -345,17 +345,17 @@ void main()
// Green: Roughness // Green: Roughness
// Blue: Metallic // Blue: Metallic
highp float metalness = vertMetalness; float metalness = vertMetalness;
if (metalnessMapEnabled == 1) { if (metalnessMapEnabled == 1) {
metalness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b; metalness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).b;
} }
highp float roughness = vertRoughness; float roughness = vertRoughness;
if (roughnessMapEnabled == 1) { if (roughnessMapEnabled == 1) {
roughness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g; roughness = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).g;
} }
highp float ambientOcclusion = 1.0; float ambientOcclusion = 1.0;
if (ambientOcclusionMapEnabled == 1) { if (ambientOcclusionMapEnabled == 1) {
ambientOcclusion = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r; ambientOcclusion = texture2D(metalnessRoughnessAmbientOcclusionMapId, vertTexCoord).r;
} }

View File

@ -1,28 +1,28 @@
attribute highp vec4 vertex; attribute vec4 vertex;
attribute highp vec3 normal; attribute vec3 normal;
attribute highp vec3 color; attribute vec3 color;
attribute highp vec2 texCoord; attribute vec2 texCoord;
attribute highp float metalness; attribute float metalness;
attribute highp float roughness; attribute float roughness;
attribute highp vec3 tangent; attribute vec3 tangent;
attribute highp float alpha; attribute float alpha;
varying highp vec3 vert; varying vec3 vert;
varying highp vec3 vertRaw; varying vec3 vertRaw;
varying highp vec3 vertNormal; varying vec3 vertNormal;
varying highp vec3 vertColor; varying vec3 vertColor;
varying highp vec2 vertTexCoord; varying vec2 vertTexCoord;
varying highp float vertMetalness; varying float vertMetalness;
varying highp float vertRoughness; varying float vertRoughness;
varying highp vec3 cameraPos; varying vec3 cameraPos;
varying highp vec3 firstLightPos; varying vec3 firstLightPos;
varying highp vec3 secondLightPos; varying vec3 secondLightPos;
varying highp vec3 thirdLightPos; varying vec3 thirdLightPos;
varying highp float vertAlpha; varying float vertAlpha;
uniform highp mat4 projectionMatrix; uniform mat4 projectionMatrix;
uniform highp mat4 modelMatrix; uniform mat4 modelMatrix;
uniform highp mat3 normalMatrix; uniform mat3 normalMatrix;
uniform highp mat4 viewMatrix; uniform mat4 viewMatrix;
uniform highp int normalMapEnabled; uniform int normalMapEnabled;
mat3 transpose(mat3 m) mat3 transpose(mat3 m)
{ {

523
src/ddsfile.cpp Normal file
View File

@ -0,0 +1,523 @@
#include <QtGlobal>
#include <QFile>
#include <QDebug>
#include <QtEndian>
#include <QByteArray>
#include <QOpenGLPixelTransferOptions>
#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<quint32>(&fileHeader.dwMagic)) {
qDebug() << "Not a DDS file";
return nullptr;
}
if (0x30315844 != qFromLittleEndian<quint32>(&fileHeader.header.ddspf.dwFourCC)) {
qDebug() << "Unsupported DDS file, expected DX10 file";
return nullptr;
}
auto caps2 = qFromLittleEndian<quint32>(&fileHeader.header.dwCaps2);
if (!(DDSCAPS2_CUBEMAP & caps2)) {
qDebug() << "Unsupported DDS file, expected CUBEMAP file";
return nullptr;
}
//qDebug() << "Start anyalize DDS file...";
int width = qFromLittleEndian<quint32>(&fileHeader.header.dwWidth);
int height = qFromLittleEndian<quint32>(&fileHeader.header.dwHeight);
//qDebug() << "DDS size:" << width << "X" << height;
//auto pitchOrLinearSize = qFromLittleEndian<quint32>(&fileHeader.header.dwPitchOrLinearSize);
//qDebug() << "DDS pitch or linear size:" << pitchOrLinearSize;
auto arraySize = qFromLittleEndian<quint32>(&fileHeader.header10.arraySize);
//qDebug() << "DDS array size:" << arraySize;
auto mipMapCount = qFromLittleEndian<quint32>(&fileHeader.header.dwMipMapCount);
//qDebug() << "DDS mip map count:" << mipMapCount;
DXGI_FORMAT dxgiFormat = (DXGI_FORMAT)qFromLittleEndian<quint32>(&fileHeader.header10.dxgiFormat);
//qDebug() << "DDS dxgi format:" << DxgiFormatToString(dxgiFormat);
//qDebug() << "DDS resource dimension:" << ResourceDimensionToString((D3D10_RESOURCE_DIMENSION)qFromLittleEndian<quint32>(&fileHeader.header10.resourceDimension));
//qDebug() << "DDS misc flag:" << MiscFlagToString((UINT)qFromLittleEndian<quint32>(&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::CubeMapFace>(QOpenGLTexture::CubeMapPositiveX + face),
QOpenGLTexture::RGBA,
QOpenGLTexture::Float16,
data.constData() + dataOffset,
&uploadOptions);
dataOffset += calculateOneFaceSizeAtLevel(level);
}
}
}
return texture;
}

15
src/ddsfile.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef DUST3D_DDS_FILE_H
#define DUST3D_DDS_FILE_H
#include <QString>
#include <QOpenGLTexture>
class DdsFileReader
{
public:
DdsFileReader(const QString &filename);
QOpenGLTexture *createOpenGLTexture();
private:
QString m_filename;
};
#endif

View File

@ -7,7 +7,7 @@
#include <QApplication> #include <QApplication>
#include <QVector3D> #include <QVector3D>
#include <functional> #include <functional>
#include <QBuffer> #include <QtCore/qbuffer.h>
#include <QElapsedTimer> #include <QElapsedTimer>
#include <queue> #include <queue>
#include "document.h" #include "document.h"
@ -57,7 +57,6 @@ Document::Document() :
m_postProcessedOutcome(new Outcome), m_postProcessedOutcome(new Outcome),
m_resultTextureMesh(nullptr), m_resultTextureMesh(nullptr),
m_textureImageUpdateVersion(0), m_textureImageUpdateVersion(0),
m_sharedContextWidget(nullptr),
m_allPositionRelatedLocksEnabled(true), m_allPositionRelatedLocksEnabled(true),
m_smoothNormal(!Preferences::instance().flatShading()), m_smoothNormal(!Preferences::instance().flatShading()),
m_rigGenerator(nullptr), m_rigGenerator(nullptr),
@ -3311,11 +3310,6 @@ void Document::checkExportReadyState()
emit exportReady(); emit exportReady();
} }
void Document::setSharedContextWidget(QOpenGLWidget *sharedContextWidget)
{
m_sharedContextWidget = sharedContextWidget;
}
void Document::collectComponentDescendantParts(QUuid componentId, std::vector<QUuid> &partIds) const void Document::collectComponentDescendantParts(QUuid componentId, std::vector<QUuid> &partIds) const
{ {
const Component *component = findComponent(componentId); const Component *component = findComponent(componentId);

View File

@ -9,7 +9,6 @@
#include <QImage> #include <QImage>
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
#include <QOpenGLWidget>
#include <QPolygon> #include <QPolygon>
#include "snapshot.h" #include "snapshot.h"
#include "meshloader.h" #include "meshloader.h"
@ -577,7 +576,6 @@ public:
const std::vector<RiggerBone> *resultRigBones() const; const std::vector<RiggerBone> *resultRigBones() const;
const std::map<int, RiggerVertexWeights> *resultRigWeights() const; const std::map<int, RiggerVertexWeights> *resultRigWeights() const;
void updateTurnaround(const QImage &image); void updateTurnaround(const QImage &image);
void setSharedContextWidget(QOpenGLWidget *sharedContextWidget);
bool hasPastableMaterialsInClipboard() const; bool hasPastableMaterialsInClipboard() const;
bool hasPastablePosesInClipboard() const; bool hasPastablePosesInClipboard() const;
bool hasPastableMotionsInClipboard() const; bool hasPastableMotionsInClipboard() const;
@ -781,7 +779,6 @@ private: // need initialize
Outcome *m_postProcessedOutcome; Outcome *m_postProcessedOutcome;
MeshLoader *m_resultTextureMesh; MeshLoader *m_resultTextureMesh;
unsigned long long m_textureImageUpdateVersion; unsigned long long m_textureImageUpdateVersion;
QOpenGLWidget *m_sharedContextWidget;
QUuid m_currentCanvasComponentId; QUuid m_currentCanvasComponentId;
bool m_allPositionRelatedLocksEnabled; bool m_allPositionRelatedLocksEnabled;
bool m_smoothNormal; bool m_smoothNormal;

View File

@ -6,7 +6,7 @@
#include <QPushButton> #include <QPushButton>
#include <QFileDialog> #include <QFileDialog>
#include <QTabWidget> #include <QTabWidget>
#include <QBuffer> #include <QtCore/qbuffer.h>
#include <QMessageBox> #include <QMessageBox>
#include <QTimer> #include <QTimer>
#include <QMenuBar> #include <QMenuBar>
@ -311,6 +311,7 @@ DocumentWindow::DocumentWindow() :
m_modelRenderWidget->move(DocumentWindow::m_modelRenderWidgetInitialX, DocumentWindow::m_modelRenderWidgetInitialY); m_modelRenderWidget->move(DocumentWindow::m_modelRenderWidgetInitialX, DocumentWindow::m_modelRenderWidgetInitialY);
m_modelRenderWidget->setMousePickRadius(m_document->mousePickRadius()); m_modelRenderWidget->setMousePickRadius(m_document->mousePickRadius());
m_modelRenderWidget->toggleWireframe(); m_modelRenderWidget->toggleWireframe();
m_modelRenderWidget->enableEnvironmentLight();
connect(m_modelRenderWidget, &ModelWidget::mouseRayChanged, m_document, connect(m_modelRenderWidget, &ModelWidget::mouseRayChanged, m_document,
[=](const QVector3D &nearPosition, const QVector3D &farPosition) { [=](const QVector3D &nearPosition, const QVector3D &farPosition) {
@ -343,8 +344,6 @@ DocumentWindow::DocumentWindow() :
m_graphicsWidget->setModelWidget(m_modelRenderWidget); m_graphicsWidget->setModelWidget(m_modelRenderWidget);
containerWidget->setModelWidget(m_modelRenderWidget); containerWidget->setModelWidget(m_modelRenderWidget);
m_document->setSharedContextWidget(m_modelRenderWidget);
setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East); setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East);
QDockWidget *partTreeDocker = new QDockWidget(tr("Parts"), this); QDockWidget *partTreeDocker = new QDockWidget(tr("Parts"), this);

View File

@ -2,7 +2,7 @@
#include <fbxproperty.h> #include <fbxproperty.h>
#include <QDateTime> #include <QDateTime>
#include <QtMath> #include <QtMath>
#include <QBuffer> #include <QtCore/qbuffer.h>
#include <QByteArray> #include <QByteArray>
#include <QFileInfo> #include <QFileInfo>
#include "fbxfile.h" #include "fbxfile.h"

View File

@ -4,7 +4,7 @@
#include <QDataStream> #include <QDataStream>
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QBuffer> #include <QtCore/qbuffer.h>
#include "glbfile.h" #include "glbfile.h"
#include "version.h" #include "version.h"
#include "util.h" #include "util.h"

View File

@ -1,7 +1,7 @@
#include <map> #include <map>
#include <QMutex> #include <QMutex>
#include <QMutexLocker> #include <QMutexLocker>
#include <QBuffer> #include <QtCore/qbuffer.h>
#include "imageforever.h" #include "imageforever.h"
struct ImageForeverItem struct ImageForeverItem

View File

@ -19,10 +19,10 @@ int main(int argc, char ** argv)
if (translator.load(QLocale(), QLatin1String("dust3d"), QLatin1String("_"), QLatin1String(":/languages"))) if (translator.load(QLocale(), QLatin1String("dust3d"), QLatin1String("_"), QLatin1String(":/languages")))
app.installTranslator(&translator); app.installTranslator(&translator);
//QSurfaceFormat format = QSurfaceFormat::defaultFormat(); QSurfaceFormat format = QSurfaceFormat::defaultFormat();
//format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
//format.setVersion(3, 3); format.setVersion(3, 3);
//QSurfaceFormat::setDefaultFormat(format); QSurfaceFormat::setDefaultFormat(format);
// QuantumCD/Qt 5 Dark Fusion Palette // QuantumCD/Qt 5 Dark Fusion Palette
// https://gist.github.com/QuantumCD/6245215 // https://gist.github.com/QuantumCD/6245215

View File

@ -48,6 +48,7 @@ MaterialEditWidget::MaterialEditWidget(const Document *document, QWidget *parent
m_previewWidget->setMinimumSize(128, 128); m_previewWidget->setMinimumSize(128, 128);
m_previewWidget->resize(512, 512); m_previewWidget->resize(512, 512);
m_previewWidget->move(-128, -128); m_previewWidget->move(-128, -128);
m_previewWidget->enableEnvironmentLight();
QFont nameFont; QFont nameFont;
nameFont.setWeight(QFont::Light); nameFont.setWeight(QFont::Light);

View File

@ -12,6 +12,7 @@ MaterialWidget::MaterialWidget(const Document *document, QUuid materialId) :
m_previewWidget->setFixedSize(Theme::materialPreviewImageSize, Theme::materialPreviewImageSize); m_previewWidget->setFixedSize(Theme::materialPreviewImageSize, Theme::materialPreviewImageSize);
m_previewWidget->enableMove(false); m_previewWidget->enableMove(false);
m_previewWidget->enableZoom(false); m_previewWidget->enableZoom(false);
m_previewWidget->enableEnvironmentLight();
m_nameLabel = new QLabel; m_nameLabel = new QLabel;
m_nameLabel->setAlignment(Qt::AlignCenter); m_nameLabel->setAlignment(Qt::AlignCenter);

View File

@ -5,8 +5,9 @@
#include <map> #include <map>
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
#include <QSurfaceFormat>
#include "modelmeshbinder.h" #include "modelmeshbinder.h"
#include "ds3file.h" #include "ddsfile.h"
ModelMeshBinder::ModelMeshBinder(bool toolEnabled) : ModelMeshBinder::ModelMeshBinder(bool toolEnabled) :
m_toolEnabled(toolEnabled) m_toolEnabled(toolEnabled)
@ -20,6 +21,8 @@ ModelMeshBinder::~ModelMeshBinder()
delete m_texture; delete m_texture;
delete m_normalMap; delete m_normalMap;
delete m_metalnessRoughnessAmbientOcclusionMap; delete m_metalnessRoughnessAmbientOcclusionMap;
delete m_environmentIrradianceMap;
delete m_environmentSpecularMap;
} }
void ModelMeshBinder::updateMesh(MeshLoader *mesh) void ModelMeshBinder::updateMesh(MeshLoader *mesh)
@ -53,6 +56,11 @@ void ModelMeshBinder::initialize()
m_vaoTool.create(); m_vaoTool.create();
} }
void ModelMeshBinder::enableEnvironmentLight()
{
m_environmentLightEnabled = true;
}
void ModelMeshBinder::paint(ModelShaderProgram *program) void ModelMeshBinder::paint(ModelShaderProgram *program)
{ {
MeshLoader *newMesh = nullptr; MeshLoader *newMesh = nullptr;
@ -72,7 +80,6 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
delete m_mesh; delete m_mesh;
m_mesh = newMesh; m_mesh = newMesh;
if (m_mesh) { if (m_mesh) {
m_hasTexture = nullptr != m_mesh->textureImage(); m_hasTexture = nullptr != m_mesh->textureImage();
delete m_texture; delete m_texture;
m_texture = nullptr; m_texture = nullptr;
@ -101,7 +108,20 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
if (nullptr != m_mesh->metalnessRoughnessAmbientOcclusionImage() && if (nullptr != m_mesh->metalnessRoughnessAmbientOcclusionImage() &&
(m_hasMetalnessMap || m_hasRoughnessMap || m_hasAmbientOcclusionMap)) (m_hasMetalnessMap || m_hasRoughnessMap || m_hasAmbientOcclusionMap))
m_metalnessRoughnessAmbientOcclusionMap = new QOpenGLTexture(*m_mesh->metalnessRoughnessAmbientOcclusionImage()); m_metalnessRoughnessAmbientOcclusionMap = new QOpenGLTexture(*m_mesh->metalnessRoughnessAmbientOcclusionImage());
delete m_environmentIrradianceMap;
m_environmentIrradianceMap = nullptr;
delete m_environmentSpecularMap;
m_environmentSpecularMap = nullptr;
if (program->isCoreProfile() && m_environmentLightEnabled &&
(m_hasMetalnessMap || m_hasRoughnessMap)) {
DdsFileReader irradianceFile(":/resources/cedar_bridge_irradiance.dds");
m_environmentIrradianceMap = irradianceFile.createOpenGLTexture();
DdsFileReader specularFile(":/resources/cedar_bridge_specular.dds");
m_environmentSpecularMap = specularFile.createOpenGLTexture();
}
{ {
QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoTriangle); QOpenGLVertexArrayObject::Binder vaoBinder(&m_vaoTriangle);
if (m_vboTriangle.isCreated()) if (m_vboTriangle.isCreated())
@ -215,6 +235,10 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
program->setUniformValue(program->metalnessMapEnabledLoc(), 0); program->setUniformValue(program->metalnessMapEnabledLoc(), 0);
program->setUniformValue(program->roughnessMapEnabledLoc(), 0); program->setUniformValue(program->roughnessMapEnabledLoc(), 0);
program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), 0); program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), 0);
if (program->isCoreProfile()) {
program->setUniformValue(program->environmentIrradianceMapEnabledLoc(), 0);
program->setUniformValue(program->environmentSpecularMapEnabledLoc(), 0);
}
f->glDrawArrays(GL_LINES, 0, m_renderEdgeVertexCount); f->glDrawArrays(GL_LINES, 0, m_renderEdgeVertexCount);
} }
} }
@ -246,6 +270,22 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
program->setUniformValue(program->metalnessMapEnabledLoc(), m_hasMetalnessMap ? 1 : 0); program->setUniformValue(program->metalnessMapEnabledLoc(), m_hasMetalnessMap ? 1 : 0);
program->setUniformValue(program->roughnessMapEnabledLoc(), m_hasRoughnessMap ? 1 : 0); program->setUniformValue(program->roughnessMapEnabledLoc(), m_hasRoughnessMap ? 1 : 0);
program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), m_hasAmbientOcclusionMap ? 1 : 0); program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), m_hasAmbientOcclusionMap ? 1 : 0);
if (program->isCoreProfile()) {
if (nullptr != m_environmentIrradianceMap) {
m_environmentIrradianceMap->bind(3);
program->setUniformValue(program->environmentIrradianceMapIdLoc(), 3);
program->setUniformValue(program->environmentIrradianceMapEnabledLoc(), 1);
} else {
program->setUniformValue(program->environmentIrradianceMapEnabledLoc(), 0);
}
if (nullptr != m_environmentSpecularMap) {
m_environmentSpecularMap->bind(4);
program->setUniformValue(program->environmentSpecularMapIdLoc(), 4);
program->setUniformValue(program->environmentSpecularMapEnabledLoc(), 1);
} else {
program->setUniformValue(program->environmentSpecularMapEnabledLoc(), 0);
}
}
f->glDrawArrays(GL_TRIANGLES, 0, m_renderTriangleVertexCount); f->glDrawArrays(GL_TRIANGLES, 0, m_renderTriangleVertexCount);
} }
if (m_toolEnabled) { if (m_toolEnabled) {
@ -257,6 +297,10 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
program->setUniformValue(program->metalnessMapEnabledLoc(), 0); program->setUniformValue(program->metalnessMapEnabledLoc(), 0);
program->setUniformValue(program->roughnessMapEnabledLoc(), 0); program->setUniformValue(program->roughnessMapEnabledLoc(), 0);
program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), 0); program->setUniformValue(program->ambientOcclusionMapEnabledLoc(), 0);
if (program->isCoreProfile()) {
program->setUniformValue(program->environmentIrradianceMapEnabledLoc(), 0);
program->setUniformValue(program->environmentSpecularMapEnabledLoc(), 0);
}
f->glDrawArrays(GL_TRIANGLES, 0, m_renderToolVertexCount); f->glDrawArrays(GL_TRIANGLES, 0, m_renderToolVertexCount);
} }
} }

View File

@ -22,6 +22,7 @@ public:
bool isWireframesVisible(); bool isWireframesVisible();
void enableCheckUv(); void enableCheckUv();
void disableCheckUv(); void disableCheckUv();
void enableEnvironmentLight();
bool isCheckUvEnabled(); bool isCheckUvEnabled();
void reloadMesh(); void reloadMesh();
private: private:
@ -42,6 +43,9 @@ private:
QOpenGLTexture *m_metalnessRoughnessAmbientOcclusionMap = nullptr; QOpenGLTexture *m_metalnessRoughnessAmbientOcclusionMap = nullptr;
bool m_toolEnabled = false; bool m_toolEnabled = false;
bool m_checkUvEnabled = false; bool m_checkUvEnabled = false;
bool m_environmentLightEnabled = false;
QOpenGLTexture *m_environmentIrradianceMap = nullptr;
QOpenGLTexture *m_environmentSpecularMap = nullptr;
private: private:
QOpenGLVertexArrayObject m_vaoTriangle; QOpenGLVertexArrayObject m_vaoTriangle;
QOpenGLBuffer m_vboTriangle; QOpenGLBuffer m_vboTriangle;

View File

@ -17,11 +17,17 @@ const QString &ModelShaderProgram::loadShaderSource(const QString &name)
return insertResult.first->second; return insertResult.first->second;
} }
bool ModelShaderProgram::isCoreProfile()
{
return m_isCoreProfile;
}
ModelShaderProgram::ModelShaderProgram() ModelShaderProgram::ModelShaderProgram()
{ {
if (QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile) { if (QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile) {
this->addShaderFromSourceCode(QOpenGLShader::Vertex, loadShaderSource(":/shaders/default.core.vert")); this->addShaderFromSourceCode(QOpenGLShader::Vertex, loadShaderSource(":/shaders/default.core.vert"));
this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.core.frag")); this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.core.frag"));
m_isCoreProfile = true;
} else { } else {
this->addShaderFromSourceCode(QOpenGLShader::Vertex, loadShaderSource(":/shaders/default.vert")); this->addShaderFromSourceCode(QOpenGLShader::Vertex, loadShaderSource(":/shaders/default.vert"));
this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.frag")); this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.frag"));
@ -53,6 +59,12 @@ ModelShaderProgram::ModelShaderProgram()
m_mousePickEnabledLoc = this->uniformLocation("mousePickEnabled"); m_mousePickEnabledLoc = this->uniformLocation("mousePickEnabled");
m_mousePickTargetPositionLoc = this->uniformLocation("mousePickTargetPosition"); m_mousePickTargetPositionLoc = this->uniformLocation("mousePickTargetPosition");
m_mousePickRadiusLoc = this->uniformLocation("mousePickRadius"); m_mousePickRadiusLoc = this->uniformLocation("mousePickRadius");
if (m_isCoreProfile) {
m_environmentIrradianceMapIdLoc = this->uniformLocation("environmentIrradianceMapId");
m_environmentIrradianceMapEnabledLoc = this->uniformLocation("environmentIrradianceMapEnabled");
m_environmentSpecularMapIdLoc = this->uniformLocation("environmentSpecularMapId");
m_environmentSpecularMapEnabledLoc = this->uniformLocation("environmentSpecularMapEnabled");
}
} }
int ModelShaderProgram::projectionMatrixLoc() int ModelShaderProgram::projectionMatrixLoc()
@ -134,3 +146,24 @@ int ModelShaderProgram::mousePickRadiusLoc()
{ {
return m_mousePickRadiusLoc; return m_mousePickRadiusLoc;
} }
int ModelShaderProgram::environmentIrradianceMapIdLoc()
{
return m_environmentIrradianceMapIdLoc;
}
int ModelShaderProgram::environmentIrradianceMapEnabledLoc()
{
return m_environmentIrradianceMapEnabledLoc;
}
int ModelShaderProgram::environmentSpecularMapIdLoc()
{
return m_environmentSpecularMapIdLoc;
}
int ModelShaderProgram::environmentSpecularMapEnabledLoc()
{
return m_environmentSpecularMapEnabledLoc;
}

View File

@ -23,24 +23,34 @@ public:
int mousePickEnabledLoc(); int mousePickEnabledLoc();
int mousePickTargetPositionLoc(); int mousePickTargetPositionLoc();
int mousePickRadiusLoc(); int mousePickRadiusLoc();
int environmentIrradianceMapIdLoc();
int environmentIrradianceMapEnabledLoc();
int environmentSpecularMapIdLoc();
int environmentSpecularMapEnabledLoc();
bool isCoreProfile();
static const QString &loadShaderSource(const QString &name); static const QString &loadShaderSource(const QString &name);
private: private:
int m_projectionMatrixLoc; bool m_isCoreProfile = false;
int m_modelMatrixLoc; int m_projectionMatrixLoc = 0;
int m_normalMatrixLoc; int m_modelMatrixLoc = 0;
int m_viewMatrixLoc; int m_normalMatrixLoc = 0;
int m_lightPosLoc; int m_viewMatrixLoc = 0;
int m_textureIdLoc; int m_lightPosLoc = 0;
int m_textureEnabledLoc; int m_textureIdLoc = 0;
int m_normalMapEnabledLoc; int m_textureEnabledLoc = 0;
int m_normalMapIdLoc; int m_normalMapEnabledLoc = 0;
int m_metalnessMapEnabledLoc; int m_normalMapIdLoc = 0;
int m_roughnessMapEnabledLoc; int m_metalnessMapEnabledLoc = 0;
int m_ambientOcclusionMapEnabledLoc; int m_roughnessMapEnabledLoc = 0;
int m_metalnessRoughnessAmbientOcclusionMapIdLoc; int m_ambientOcclusionMapEnabledLoc = 0;
int m_mousePickEnabledLoc; int m_metalnessRoughnessAmbientOcclusionMapIdLoc = 0;
int m_mousePickTargetPositionLoc; int m_mousePickEnabledLoc = 0;
int m_mousePickRadiusLoc; int m_mousePickTargetPositionLoc = 0;
int m_mousePickRadiusLoc = 0;
int m_environmentIrradianceMapIdLoc = 0;
int m_environmentIrradianceMapEnabledLoc = 0;
int m_environmentSpecularMapIdLoc = 0;
int m_environmentSpecularMapEnabledLoc = 0;
}; };
#endif #endif

View File

@ -211,6 +211,12 @@ void ModelWidget::toggleWireframe()
update(); update();
} }
void ModelWidget::enableEnvironmentLight()
{
m_meshBinder.enableEnvironmentLight();
update();
}
void ModelWidget::toggleRotation() void ModelWidget::toggleRotation()
{ {
if (nullptr != m_rotationTimer) { if (nullptr != m_rotationTimer) {

View File

@ -39,6 +39,7 @@ public:
void toggleWireframe(); void toggleWireframe();
void toggleRotation(); void toggleRotation();
void toggleUvCheck(); void toggleUvCheck();
void enableEnvironmentLight();
void enableMove(bool enabled); void enableMove(bool enabled);
void enableZoom(bool enabled); void enableZoom(bool enabled);
void enableMousePicking(bool enabled); void enableMousePicking(bool enabled);