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

View File

@ -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

View File

@ -23,6 +23,8 @@
<file>resources/heptagon.png</file>
<file>resources/userdefined.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.frag</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
// 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,

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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)
{

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 <QVector3D>
#include <functional>
#include <QBuffer>
#include <QtCore/qbuffer.h>
#include <QElapsedTimer>
#include <queue>
#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<QUuid> &partIds) const
{
const Component *component = findComponent(componentId);

View File

@ -9,7 +9,6 @@
#include <QImage>
#include <cmath>
#include <algorithm>
#include <QOpenGLWidget>
#include <QPolygon>
#include "snapshot.h"
#include "meshloader.h"
@ -577,7 +576,6 @@ public:
const std::vector<RiggerBone> *resultRigBones() const;
const std::map<int, RiggerVertexWeights> *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;

View File

@ -6,7 +6,7 @@
#include <QPushButton>
#include <QFileDialog>
#include <QTabWidget>
#include <QBuffer>
#include <QtCore/qbuffer.h>
#include <QMessageBox>
#include <QTimer>
#include <QMenuBar>
@ -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);

View File

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

View File

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

View File

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

View File

@ -19,10 +19,10 @@ int main(int argc, char ** argv)
if (translator.load(QLocale(), QLatin1String("dust3d"), QLatin1String("_"), QLatin1String(":/languages")))
app.installTranslator(&translator);
//QSurfaceFormat format = QSurfaceFormat::defaultFormat();
//format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
//format.setVersion(3, 3);
//QSurfaceFormat::setDefaultFormat(format);
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
format.setVersion(3, 3);
QSurfaceFormat::setDefaultFormat(format);
// QuantumCD/Qt 5 Dark Fusion Palette
// 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->resize(512, 512);
m_previewWidget->move(-128, -128);
m_previewWidget->enableEnvironmentLight();
QFont nameFont;
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->enableMove(false);
m_previewWidget->enableZoom(false);
m_previewWidget->enableEnvironmentLight();
m_nameLabel = new QLabel;
m_nameLabel->setAlignment(Qt::AlignCenter);

View File

@ -5,8 +5,9 @@
#include <map>
#include <QDebug>
#include <QDir>
#include <QSurfaceFormat>
#include "modelmeshbinder.h"
#include "ds3file.h"
#include "ddsfile.h"
ModelMeshBinder::ModelMeshBinder(bool toolEnabled) :
m_toolEnabled(toolEnabled)
@ -20,6 +21,8 @@ ModelMeshBinder::~ModelMeshBinder()
delete m_texture;
delete m_normalMap;
delete m_metalnessRoughnessAmbientOcclusionMap;
delete m_environmentIrradianceMap;
delete m_environmentSpecularMap;
}
void ModelMeshBinder::updateMesh(MeshLoader *mesh)
@ -53,6 +56,11 @@ void ModelMeshBinder::initialize()
m_vaoTool.create();
}
void ModelMeshBinder::enableEnvironmentLight()
{
m_environmentLightEnabled = true;
}
void ModelMeshBinder::paint(ModelShaderProgram *program)
{
MeshLoader *newMesh = nullptr;
@ -72,7 +80,6 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
delete m_mesh;
m_mesh = newMesh;
if (m_mesh) {
m_hasTexture = nullptr != m_mesh->textureImage();
delete m_texture;
m_texture = nullptr;
@ -101,7 +108,20 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
if (nullptr != m_mesh->metalnessRoughnessAmbientOcclusionImage() &&
(m_hasMetalnessMap || m_hasRoughnessMap || m_hasAmbientOcclusionMap))
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);
if (m_vboTriangle.isCreated())
@ -215,6 +235,10 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
program->setUniformValue(program->metalnessMapEnabledLoc(), 0);
program->setUniformValue(program->roughnessMapEnabledLoc(), 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);
}
}
@ -246,6 +270,22 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
program->setUniformValue(program->metalnessMapEnabledLoc(), m_hasMetalnessMap ? 1 : 0);
program->setUniformValue(program->roughnessMapEnabledLoc(), m_hasRoughnessMap ? 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);
}
if (m_toolEnabled) {
@ -257,6 +297,10 @@ void ModelMeshBinder::paint(ModelShaderProgram *program)
program->setUniformValue(program->metalnessMapEnabledLoc(), 0);
program->setUniformValue(program->roughnessMapEnabledLoc(), 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);
}
}

View File

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

View File

@ -17,11 +17,17 @@ const QString &ModelShaderProgram::loadShaderSource(const QString &name)
return insertResult.first->second;
}
bool ModelShaderProgram::isCoreProfile()
{
return m_isCoreProfile;
}
ModelShaderProgram::ModelShaderProgram()
{
if (QSurfaceFormat::defaultFormat().profile() == QSurfaceFormat::CoreProfile) {
this->addShaderFromSourceCode(QOpenGLShader::Vertex, loadShaderSource(":/shaders/default.core.vert"));
this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.core.frag"));
m_isCoreProfile = true;
} else {
this->addShaderFromSourceCode(QOpenGLShader::Vertex, loadShaderSource(":/shaders/default.vert"));
this->addShaderFromSourceCode(QOpenGLShader::Fragment, loadShaderSource(":/shaders/default.frag"));
@ -53,6 +59,12 @@ ModelShaderProgram::ModelShaderProgram()
m_mousePickEnabledLoc = this->uniformLocation("mousePickEnabled");
m_mousePickTargetPositionLoc = this->uniformLocation("mousePickTargetPosition");
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()
@ -134,3 +146,24 @@ int ModelShaderProgram::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 mousePickTargetPositionLoc();
int mousePickRadiusLoc();
int environmentIrradianceMapIdLoc();
int environmentIrradianceMapEnabledLoc();
int environmentSpecularMapIdLoc();
int environmentSpecularMapEnabledLoc();
bool isCoreProfile();
static const QString &loadShaderSource(const QString &name);
private:
int m_projectionMatrixLoc;
int m_modelMatrixLoc;
int m_normalMatrixLoc;
int m_viewMatrixLoc;
int m_lightPosLoc;
int m_textureIdLoc;
int m_textureEnabledLoc;
int m_normalMapEnabledLoc;
int m_normalMapIdLoc;
int m_metalnessMapEnabledLoc;
int m_roughnessMapEnabledLoc;
int m_ambientOcclusionMapEnabledLoc;
int m_metalnessRoughnessAmbientOcclusionMapIdLoc;
int m_mousePickEnabledLoc;
int m_mousePickTargetPositionLoc;
int m_mousePickRadiusLoc;
bool m_isCoreProfile = false;
int m_projectionMatrixLoc = 0;
int m_modelMatrixLoc = 0;
int m_normalMatrixLoc = 0;
int m_viewMatrixLoc = 0;
int m_lightPosLoc = 0;
int m_textureIdLoc = 0;
int m_textureEnabledLoc = 0;
int m_normalMapEnabledLoc = 0;
int m_normalMapIdLoc = 0;
int m_metalnessMapEnabledLoc = 0;
int m_roughnessMapEnabledLoc = 0;
int m_ambientOcclusionMapEnabledLoc = 0;
int m_metalnessRoughnessAmbientOcclusionMapIdLoc = 0;
int m_mousePickEnabledLoc = 0;
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

View File

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

View File

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