mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +02:00
Merge pull request #3859 from samcake/tot
support texture transform and lightmap
This commit is contained in:
commit
c5e923f091
24 changed files with 1038 additions and 174 deletions
|
@ -11,6 +11,10 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const int MAX_TEXCOORDS = 2;
|
||||||
|
|
||||||
|
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
|
||||||
|
|
||||||
// the interpolated normal
|
// the interpolated normal
|
||||||
varying vec4 normal;
|
varying vec4 normal;
|
||||||
|
|
||||||
|
@ -22,7 +26,7 @@ void main(void) {
|
||||||
gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse;
|
gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse;
|
||||||
|
|
||||||
// and the texture coordinates
|
// and the texture coordinates
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
||||||
|
|
||||||
// use standard pipeline transform
|
// use standard pipeline transform
|
||||||
gl_Position = ftransform();
|
gl_Position = ftransform();
|
||||||
|
|
37
interface/resources/shaders/model_lightmap.frag
Normal file
37
interface/resources/shaders/model_lightmap.frag
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// model_lightmap.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Samuel Gateau on 11/19/14.
|
||||||
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// the diffuse texture
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
|
// the emissive map texture and parameters
|
||||||
|
uniform sampler2D emissiveMap;
|
||||||
|
uniform vec2 emissiveParams;
|
||||||
|
|
||||||
|
// the alpha threshold
|
||||||
|
uniform float alphaThreshold;
|
||||||
|
|
||||||
|
// the interpolated normal
|
||||||
|
varying vec4 normal;
|
||||||
|
|
||||||
|
// the interpolated texcoord1
|
||||||
|
varying vec2 interpolatedTexcoord1;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// set the diffuse, normal, specular data
|
||||||
|
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||||
|
vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st);
|
||||||
|
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
|
||||||
|
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||||
|
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0);
|
||||||
|
}
|
40
interface/resources/shaders/model_lightmap.vert
Normal file
40
interface/resources/shaders/model_lightmap.vert
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// model_lightmap.vert
|
||||||
|
// vertex shader
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 11/21/14.
|
||||||
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
const int MAX_TEXCOORDS = 2;
|
||||||
|
|
||||||
|
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
|
||||||
|
|
||||||
|
attribute vec2 texcoord1;
|
||||||
|
|
||||||
|
// the interpolated normal
|
||||||
|
varying vec4 normal;
|
||||||
|
|
||||||
|
// the interpolated texcoord1
|
||||||
|
varying vec2 interpolatedTexcoord1;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// transform and store the normal for interpolation
|
||||||
|
normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
|
||||||
|
|
||||||
|
// pass along the diffuse color
|
||||||
|
gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse;
|
||||||
|
|
||||||
|
// and the texture coordinates
|
||||||
|
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
||||||
|
interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy;
|
||||||
|
|
||||||
|
// use standard pipeline transform
|
||||||
|
gl_Position = ftransform();
|
||||||
|
}
|
||||||
|
|
50
interface/resources/shaders/model_lightmap_normal_map.frag
Normal file
50
interface/resources/shaders/model_lightmap_normal_map.frag
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// model_lightmap_normal_map.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Samuel Gateau on 11/19/14.
|
||||||
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// the diffuse texture
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
|
// the normal map texture
|
||||||
|
uniform sampler2D normalMap;
|
||||||
|
|
||||||
|
// the emissive map texture and parameters
|
||||||
|
uniform sampler2D emissiveMap;
|
||||||
|
uniform vec2 emissiveParams;
|
||||||
|
|
||||||
|
// the alpha threshold
|
||||||
|
uniform float alphaThreshold;
|
||||||
|
|
||||||
|
// the interpolated normal
|
||||||
|
varying vec4 interpolatedNormal;
|
||||||
|
|
||||||
|
// the interpolated tangent
|
||||||
|
varying vec4 interpolatedTangent;
|
||||||
|
|
||||||
|
varying vec2 interpolatedTexcoord1;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// compute the view normal from the various bits
|
||||||
|
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||||
|
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||||
|
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||||
|
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5);
|
||||||
|
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||||
|
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||||
|
|
||||||
|
// set the diffuse, normal, specular data
|
||||||
|
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||||
|
vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st);
|
||||||
|
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
|
||||||
|
gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0);
|
||||||
|
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb, gl_FrontMaterial.shininess / 128.0);
|
||||||
|
}
|
46
interface/resources/shaders/model_lightmap_normal_map.vert
Normal file
46
interface/resources/shaders/model_lightmap_normal_map.vert
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// model_lightmap_normal_map.vert
|
||||||
|
// vertex shader
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 11/21/14.
|
||||||
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
const int MAX_TEXCOORDS = 2;
|
||||||
|
|
||||||
|
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
|
||||||
|
|
||||||
|
// the tangent vector
|
||||||
|
attribute vec3 tangent;
|
||||||
|
|
||||||
|
attribute vec2 texcoord1;
|
||||||
|
|
||||||
|
// the interpolated normal
|
||||||
|
varying vec4 interpolatedNormal;
|
||||||
|
|
||||||
|
// the interpolated tangent
|
||||||
|
varying vec4 interpolatedTangent;
|
||||||
|
|
||||||
|
// the interpolated texcoord1
|
||||||
|
varying vec2 interpolatedTexcoord1;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// transform and store the normal and tangent for interpolation
|
||||||
|
interpolatedNormal = gl_ModelViewMatrix * vec4(gl_Normal, 0.0);
|
||||||
|
interpolatedTangent = gl_ModelViewMatrix * vec4(tangent, 0.0);
|
||||||
|
|
||||||
|
// pass along the diffuse color
|
||||||
|
gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse;
|
||||||
|
|
||||||
|
// and the texture coordinates
|
||||||
|
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
||||||
|
interpolatedTexcoord1 = vec2(texcoordMatrices[1] * vec4(texcoord1.xy, 0.0, 1.0)).xy;
|
||||||
|
|
||||||
|
// use standard pipeline transform
|
||||||
|
gl_Position = ftransform();
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// model_lightmap_normal_specular_map.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Samuel Gateau on 11/19/14.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// the diffuse texture
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
|
// the emissive map texture and parameters
|
||||||
|
uniform sampler2D emissiveMap;
|
||||||
|
uniform vec2 emissiveParams;
|
||||||
|
|
||||||
|
// the normal map texture
|
||||||
|
uniform sampler2D normalMap;
|
||||||
|
|
||||||
|
// the specular map texture
|
||||||
|
uniform sampler2D specularMap;
|
||||||
|
|
||||||
|
// the alpha threshold
|
||||||
|
uniform float alphaThreshold;
|
||||||
|
|
||||||
|
// the interpolated normal
|
||||||
|
varying vec4 interpolatedNormal;
|
||||||
|
|
||||||
|
// the interpolated tangent
|
||||||
|
varying vec4 interpolatedTangent;
|
||||||
|
|
||||||
|
varying vec2 interpolatedTexcoord1;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// compute the view normal from the various bits
|
||||||
|
vec3 normalizedNormal = normalize(vec3(interpolatedNormal));
|
||||||
|
vec3 normalizedTangent = normalize(vec3(interpolatedTangent));
|
||||||
|
vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent));
|
||||||
|
vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5);
|
||||||
|
vec4 viewNormal = vec4(normalizedTangent * localNormal.x +
|
||||||
|
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||||
|
|
||||||
|
// set the diffuse, normal, specular data
|
||||||
|
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||||
|
vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st);
|
||||||
|
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
|
||||||
|
gl_FragData[1] = viewNormal + vec4(0.5, 0.5, 0.5, 1.0);
|
||||||
|
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb,
|
||||||
|
gl_FrontMaterial.shininess / 128.0);
|
||||||
|
}
|
40
interface/resources/shaders/model_lightmap_specular_map.frag
Normal file
40
interface/resources/shaders/model_lightmap_specular_map.frag
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
//
|
||||||
|
// model_lightmap_specular_map.frag
|
||||||
|
// fragment shader
|
||||||
|
//
|
||||||
|
// Created by Samuel Gateau on 11/19/14.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// the diffuse texture
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
|
// the emissive map texture and parameters
|
||||||
|
uniform sampler2D emissiveMap;
|
||||||
|
uniform vec2 emissiveParams;
|
||||||
|
|
||||||
|
// the specular texture
|
||||||
|
uniform sampler2D specularMap;
|
||||||
|
|
||||||
|
// the alpha threshold
|
||||||
|
uniform float alphaThreshold;
|
||||||
|
|
||||||
|
// the interpolated normal
|
||||||
|
varying vec4 normal;
|
||||||
|
|
||||||
|
varying vec2 interpolatedTexcoord1;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
// set the diffuse, normal, specular data
|
||||||
|
vec4 diffuse = texture2D(diffuseMap, gl_TexCoord[0].st);
|
||||||
|
vec4 emissive = texture2D(emissiveMap, interpolatedTexcoord1.st);
|
||||||
|
gl_FragData[0] = vec4(gl_Color.rgb * diffuse.rgb * (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb), mix(gl_Color.a, 1.0 - gl_Color.a, step(diffuse.a, alphaThreshold)));
|
||||||
|
gl_FragData[1] = normalize(normal) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0);
|
||||||
|
gl_FragData[2] = vec4(gl_FrontMaterial.specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb,
|
||||||
|
gl_FrontMaterial.shininess / 128.0);
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
// model_normal_map.frag
|
// model_normal_map.frag
|
||||||
// fragment shader
|
// fragment shader
|
||||||
//
|
//
|
||||||
// Created by Andrzej Kapolka on 10/29/13.
|
// Created by Andrzej Kapolka on 10/14/13.
|
||||||
// Copyright 2013 High Fidelity, Inc.
|
// Copyright 2013 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const int MAX_TEXCOORDS = 2;
|
||||||
|
|
||||||
|
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
|
||||||
|
|
||||||
// the tangent vector
|
// the tangent vector
|
||||||
attribute vec3 tangent;
|
attribute vec3 tangent;
|
||||||
|
|
||||||
|
@ -29,7 +33,7 @@ void main(void) {
|
||||||
gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse;
|
gl_FrontColor = gl_Color * gl_FrontMaterial.diffuse;
|
||||||
|
|
||||||
// and the texture coordinates
|
// and the texture coordinates
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
||||||
|
|
||||||
// use standard pipeline transform
|
// use standard pipeline transform
|
||||||
gl_Position = ftransform();
|
gl_Position = ftransform();
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const int MAX_TEXCOORDS = 2;
|
||||||
const int MAX_CLUSTERS = 128;
|
const int MAX_CLUSTERS = 128;
|
||||||
const int INDICES_PER_VERTEX = 4;
|
const int INDICES_PER_VERTEX = 4;
|
||||||
|
|
||||||
uniform mat4 clusterMatrices[MAX_CLUSTERS];
|
uniform mat4 clusterMatrices[MAX_CLUSTERS];
|
||||||
|
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
|
||||||
|
|
||||||
attribute vec4 clusterIndices;
|
attribute vec4 clusterIndices;
|
||||||
attribute vec4 clusterWeights;
|
attribute vec4 clusterWeights;
|
||||||
|
@ -38,7 +40,7 @@ void main(void) {
|
||||||
gl_FrontColor = gl_FrontMaterial.diffuse;
|
gl_FrontColor = gl_FrontMaterial.diffuse;
|
||||||
|
|
||||||
// and the texture coordinates
|
// and the texture coordinates
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
||||||
|
|
||||||
gl_Position = gl_ModelViewProjectionMatrix * position;
|
gl_Position = gl_ModelViewProjectionMatrix * position;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,12 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const int MAX_TEXCOORDS = 2;
|
||||||
const int MAX_CLUSTERS = 128;
|
const int MAX_CLUSTERS = 128;
|
||||||
const int INDICES_PER_VERTEX = 4;
|
const int INDICES_PER_VERTEX = 4;
|
||||||
|
|
||||||
uniform mat4 clusterMatrices[MAX_CLUSTERS];
|
uniform mat4 clusterMatrices[MAX_CLUSTERS];
|
||||||
|
uniform mat4 texcoordMatrices[MAX_TEXCOORDS];
|
||||||
|
|
||||||
// the tangent vector
|
// the tangent vector
|
||||||
attribute vec3 tangent;
|
attribute vec3 tangent;
|
||||||
|
@ -46,7 +48,7 @@ void main(void) {
|
||||||
gl_FrontColor = gl_FrontMaterial.diffuse;
|
gl_FrontColor = gl_FrontMaterial.diffuse;
|
||||||
|
|
||||||
// and the texture coordinates
|
// and the texture coordinates
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0);
|
||||||
|
|
||||||
gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition;
|
gl_Position = gl_ModelViewProjectionMatrix * interpolatedPosition;
|
||||||
}
|
}
|
||||||
|
|
|
@ -522,6 +522,14 @@ bool ModelUploader::addTextures(const QString& texdir, const FBXGeometry& geomet
|
||||||
}
|
}
|
||||||
_textureFilenames.insert(part.specularTexture.filename);
|
_textureFilenames.insert(part.specularTexture.filename);
|
||||||
}
|
}
|
||||||
|
if (!part.emissiveTexture.filename.isEmpty() && part.emissiveTexture.content.isEmpty() &&
|
||||||
|
!_textureFilenames.contains(part.emissiveTexture.filename)) {
|
||||||
|
if (!addPart(texdir + "/" + part.emissiveTexture.filename,
|
||||||
|
QString("texture%1").arg(++_texturesCount), true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_textureFilenames.insert(part.emissiveTexture.filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@ public:
|
||||||
|
|
||||||
void _glUseProgram(GLuint program);
|
void _glUseProgram(GLuint program);
|
||||||
void _glUniform1f(GLint location, GLfloat v0);
|
void _glUniform1f(GLint location, GLfloat v0);
|
||||||
|
void _glUniform2f(GLint location, GLfloat v0, GLfloat v1);
|
||||||
void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||||
|
|
||||||
void _glMatrixMode(GLenum mode);
|
void _glMatrixMode(GLenum mode);
|
||||||
|
@ -185,6 +186,7 @@ public:
|
||||||
|
|
||||||
COMMAND_glUseProgram,
|
COMMAND_glUseProgram,
|
||||||
COMMAND_glUniform1f,
|
COMMAND_glUniform1f,
|
||||||
|
COMMAND_glUniform2f,
|
||||||
COMMAND_glUniformMatrix4fv,
|
COMMAND_glUniformMatrix4fv,
|
||||||
|
|
||||||
COMMAND_glMatrixMode,
|
COMMAND_glMatrixMode,
|
||||||
|
|
|
@ -53,6 +53,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_glUseProgram),
|
(&::gpu::GLBackend::do_glUseProgram),
|
||||||
(&::gpu::GLBackend::do_glUniform1f),
|
(&::gpu::GLBackend::do_glUniform1f),
|
||||||
|
(&::gpu::GLBackend::do_glUniform2f),
|
||||||
(&::gpu::GLBackend::do_glUniformMatrix4fv),
|
(&::gpu::GLBackend::do_glUniformMatrix4fv),
|
||||||
|
|
||||||
(&::gpu::GLBackend::do_glMatrixMode),
|
(&::gpu::GLBackend::do_glMatrixMode),
|
||||||
|
@ -691,6 +692,23 @@ void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) {
|
||||||
CHECK_GL_ERROR();
|
CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Batch::_glUniform2f(GLint location, GLfloat v0, GLfloat v1) {
|
||||||
|
ADD_COMMAND_GL(glUniform2f);
|
||||||
|
|
||||||
|
_params.push_back(v1);
|
||||||
|
_params.push_back(v0);
|
||||||
|
_params.push_back(location);
|
||||||
|
|
||||||
|
DO_IT_NOW(_glUniform2f, 1);
|
||||||
|
}
|
||||||
|
void GLBackend::do_glUniform2f(Batch& batch, uint32 paramOffset) {
|
||||||
|
glUniform2f(
|
||||||
|
batch._params[paramOffset + 2]._int,
|
||||||
|
batch._params[paramOffset + 1]._float,
|
||||||
|
batch._params[paramOffset + 0]._float);
|
||||||
|
CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
void Batch::_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) {
|
||||||
ADD_COMMAND_GL(glUniformMatrix4fv);
|
ADD_COMMAND_GL(glUniformMatrix4fv);
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,7 @@ protected:
|
||||||
|
|
||||||
void do_glUseProgram(Batch& batch, uint32 paramOffset);
|
void do_glUseProgram(Batch& batch, uint32 paramOffset);
|
||||||
void do_glUniform1f(Batch& batch, uint32 paramOffset);
|
void do_glUniform1f(Batch& batch, uint32 paramOffset);
|
||||||
|
void do_glUniform2f(Batch& batch, uint32 paramOffset);
|
||||||
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
|
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void do_glMatrixMode(Batch& batch, uint32 paramOffset);
|
void do_glMatrixMode(Batch& batch, uint32 paramOffset);
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
TANGENT,
|
TANGENT,
|
||||||
SKIN_CLUSTER_INDEX,
|
SKIN_CLUSTER_INDEX,
|
||||||
SKIN_CLUSTER_WEIGHT,
|
SKIN_CLUSTER_WEIGHT,
|
||||||
|
TEXCOORD1,
|
||||||
|
|
||||||
NUM_INPUT_SLOTS,
|
NUM_INPUT_SLOTS,
|
||||||
};
|
};
|
||||||
|
|
|
@ -575,7 +575,8 @@ bool NetworkGeometry::isLoadedWithTextures() const {
|
||||||
foreach (const NetworkMeshPart& part, mesh.parts) {
|
foreach (const NetworkMeshPart& part, mesh.parts) {
|
||||||
if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) ||
|
if ((part.diffuseTexture && !part.diffuseTexture->isLoaded()) ||
|
||||||
(part.normalTexture && !part.normalTexture->isLoaded()) ||
|
(part.normalTexture && !part.normalTexture->isLoaded()) ||
|
||||||
(part.specularTexture && !part.specularTexture->isLoaded())) {
|
(part.specularTexture && !part.specularTexture->isLoaded()) ||
|
||||||
|
(part.emissiveTexture && !part.emissiveTexture->isLoaded())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -668,6 +669,9 @@ void NetworkGeometry::setLoadPriority(const QPointer<QObject>& owner, float prio
|
||||||
if (part.specularTexture) {
|
if (part.specularTexture) {
|
||||||
part.specularTexture->setLoadPriority(owner, priority);
|
part.specularTexture->setLoadPriority(owner, priority);
|
||||||
}
|
}
|
||||||
|
if (part.emissiveTexture) {
|
||||||
|
part.emissiveTexture->setLoadPriority(owner, priority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,6 +692,9 @@ void NetworkGeometry::setLoadPriorities(const QHash<QPointer<QObject>, float>& p
|
||||||
if (part.specularTexture) {
|
if (part.specularTexture) {
|
||||||
part.specularTexture->setLoadPriorities(priorities);
|
part.specularTexture->setLoadPriorities(priorities);
|
||||||
}
|
}
|
||||||
|
if (part.emissiveTexture) {
|
||||||
|
part.emissiveTexture->setLoadPriorities(priorities);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -708,6 +715,9 @@ void NetworkGeometry::clearLoadPriority(const QPointer<QObject>& owner) {
|
||||||
if (part.specularTexture) {
|
if (part.specularTexture) {
|
||||||
part.specularTexture->clearLoadPriority(owner);
|
part.specularTexture->clearLoadPriority(owner);
|
||||||
}
|
}
|
||||||
|
if (part.emissiveTexture) {
|
||||||
|
part.emissiveTexture->clearLoadPriority(owner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -733,6 +743,10 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u
|
||||||
part.specularTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE,
|
part.specularTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE,
|
||||||
false, QByteArray());
|
false, QByteArray());
|
||||||
part.specularTexture->setLoadPriorities(_loadPriorities);
|
part.specularTexture->setLoadPriorities(_loadPriorities);
|
||||||
|
} else if (part.emissiveTextureName == name) {
|
||||||
|
part.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture(url, DEFAULT_TEXTURE,
|
||||||
|
false, QByteArray());
|
||||||
|
part.emissiveTexture->setLoadPriorities(_loadPriorities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -764,6 +778,11 @@ QStringList NetworkGeometry::getTextureNames() const {
|
||||||
QString textureURL = part.specularTexture->getURL().toString();
|
QString textureURL = part.specularTexture->getURL().toString();
|
||||||
result << part.specularTextureName + ":" + textureURL;
|
result << part.specularTextureName + ":" + textureURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!part.emissiveTextureName.isEmpty()) {
|
||||||
|
QString textureURL = part.emissiveTexture->getURL().toString();
|
||||||
|
result << part.emissiveTextureName + ":" + textureURL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -811,6 +830,8 @@ void GeometryReader::run() {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&,
|
QMetaObject::invokeMethod(geometry.data(), "setGeometry", Q_ARG(const FBXGeometry&,
|
||||||
|
|
||||||
|
|
||||||
_url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping)));
|
_url.path().toLower().endsWith(".svo") ? readSVO(_reply->readAll()) : readFBX(_reply->readAll(), _mapping)));
|
||||||
|
|
||||||
} catch (const QString& error) {
|
} catch (const QString& error) {
|
||||||
|
@ -911,6 +932,13 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
|
||||||
networkPart.specularTextureName = part.specularTexture.name;
|
networkPart.specularTextureName = part.specularTexture.name;
|
||||||
networkPart.specularTexture->setLoadPriorities(_loadPriorities);
|
networkPart.specularTexture->setLoadPriorities(_loadPriorities);
|
||||||
}
|
}
|
||||||
|
if (!part.emissiveTexture.filename.isEmpty()) {
|
||||||
|
networkPart.emissiveTexture = Application::getInstance()->getTextureCache()->getTexture(
|
||||||
|
_textureBase.resolved(QUrl(part.emissiveTexture.filename)), EMISSIVE_TEXTURE,
|
||||||
|
false, part.emissiveTexture.content);
|
||||||
|
networkPart.emissiveTextureName = part.emissiveTexture.name;
|
||||||
|
networkPart.emissiveTexture->setLoadPriorities(_loadPriorities);
|
||||||
|
}
|
||||||
networkMesh.parts.append(networkPart);
|
networkMesh.parts.append(networkPart);
|
||||||
|
|
||||||
totalIndices += (part.quadIndices.size() + part.triangleIndices.size());
|
totalIndices += (part.quadIndices.size() + part.triangleIndices.size());
|
||||||
|
@ -938,11 +966,11 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
|
||||||
int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3);
|
int tangentsOffset = normalsOffset + mesh.normals.size() * sizeof(glm::vec3);
|
||||||
int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3);
|
int colorsOffset = tangentsOffset + mesh.tangents.size() * sizeof(glm::vec3);
|
||||||
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
|
int texCoordsOffset = colorsOffset + mesh.colors.size() * sizeof(glm::vec3);
|
||||||
int clusterIndicesOffset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
|
int texCoords1Offset = texCoordsOffset + mesh.texCoords.size() * sizeof(glm::vec2);
|
||||||
|
int clusterIndicesOffset = texCoords1Offset + mesh.texCoords1.size() * sizeof(glm::vec2);
|
||||||
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
|
int clusterWeightsOffset = clusterIndicesOffset + mesh.clusterIndices.size() * sizeof(glm::vec4);
|
||||||
|
|
||||||
networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
|
networkMesh._vertexBuffer->resize(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
|
||||||
//networkMesh.vertexBuffer.allocate(clusterWeightsOffset + mesh.clusterWeights.size() * sizeof(glm::vec4));
|
|
||||||
|
|
||||||
networkMesh._vertexBuffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData());
|
networkMesh._vertexBuffer->setSubData(0, mesh.vertices.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.vertices.constData());
|
||||||
networkMesh._vertexBuffer->setSubData(normalsOffset, mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData());
|
networkMesh._vertexBuffer->setSubData(normalsOffset, mesh.normals.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.normals.constData());
|
||||||
|
@ -951,6 +979,8 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
|
||||||
networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData());
|
networkMesh._vertexBuffer->setSubData(colorsOffset, mesh.colors.size() * sizeof(glm::vec3), (gpu::Resource::Byte*) mesh.colors.constData());
|
||||||
networkMesh._vertexBuffer->setSubData(texCoordsOffset,
|
networkMesh._vertexBuffer->setSubData(texCoordsOffset,
|
||||||
mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData());
|
mesh.texCoords.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords.constData());
|
||||||
|
networkMesh._vertexBuffer->setSubData(texCoords1Offset,
|
||||||
|
mesh.texCoords1.size() * sizeof(glm::vec2), (gpu::Resource::Byte*) mesh.texCoords1.constData());
|
||||||
networkMesh._vertexBuffer->setSubData(clusterIndicesOffset,
|
networkMesh._vertexBuffer->setSubData(clusterIndicesOffset,
|
||||||
mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData());
|
mesh.clusterIndices.size() * sizeof(glm::vec4), (gpu::Resource::Byte*) mesh.clusterIndices.constData());
|
||||||
networkMesh._vertexBuffer->setSubData(clusterWeightsOffset,
|
networkMesh._vertexBuffer->setSubData(clusterWeightsOffset,
|
||||||
|
@ -963,6 +993,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
|
||||||
if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3));
|
if (mesh.tangents.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, tangentsOffset, sizeof(glm::vec3));
|
||||||
if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3));
|
if (mesh.colors.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, colorsOffset, sizeof(glm::vec3));
|
||||||
if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2));
|
if (mesh.texCoords.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoordsOffset, sizeof(glm::vec2));
|
||||||
|
if (mesh.texCoords1.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, texCoords1Offset, sizeof(glm::vec2));
|
||||||
if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4));
|
if (mesh.clusterIndices.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterIndicesOffset, sizeof(glm::vec4));
|
||||||
if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4));
|
if (mesh.clusterWeights.size()) networkMesh._vertexStream->addBuffer(networkMesh._vertexBuffer, clusterWeightsOffset, sizeof(glm::vec4));
|
||||||
|
|
||||||
|
@ -973,6 +1004,7 @@ void NetworkGeometry::setGeometry(const FBXGeometry& geometry) {
|
||||||
if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
if (mesh.tangents.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TANGENT, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
|
||||||
if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB));
|
if (mesh.colors.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::COLOR, channelNum++, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB));
|
||||||
if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
|
if (mesh.texCoords.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
|
||||||
|
if (mesh.texCoords1.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::TEXCOORD1, channelNum++, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
|
||||||
if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW));
|
if (mesh.clusterIndices.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_INDEX, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW));
|
||||||
if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW));
|
if (mesh.clusterWeights.size()) networkMesh._vertexFormat->setAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT, channelNum++, gpu::Element(gpu::VEC4, gpu::NFLOAT, gpu::XYZW));
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,9 @@ public:
|
||||||
QSharedPointer<NetworkTexture> normalTexture;
|
QSharedPointer<NetworkTexture> normalTexture;
|
||||||
QString specularTextureName;
|
QString specularTextureName;
|
||||||
QSharedPointer<NetworkTexture> specularTexture;
|
QSharedPointer<NetworkTexture> specularTexture;
|
||||||
|
QString emissiveTextureName;
|
||||||
|
QSharedPointer<NetworkTexture> emissiveTexture;
|
||||||
|
|
||||||
bool isTranslucent() const;
|
bool isTranslucent() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,11 @@ ProgramObject Model::_specularMapProgram;
|
||||||
ProgramObject Model::_normalSpecularMapProgram;
|
ProgramObject Model::_normalSpecularMapProgram;
|
||||||
ProgramObject Model::_translucentProgram;
|
ProgramObject Model::_translucentProgram;
|
||||||
|
|
||||||
|
ProgramObject Model::_lightmapProgram;
|
||||||
|
ProgramObject Model::_lightmapNormalMapProgram;
|
||||||
|
ProgramObject Model::_lightmapSpecularMapProgram;
|
||||||
|
ProgramObject Model::_lightmapNormalSpecularMapProgram;
|
||||||
|
|
||||||
ProgramObject Model::_shadowProgram;
|
ProgramObject Model::_shadowProgram;
|
||||||
|
|
||||||
ProgramObject Model::_skinProgram;
|
ProgramObject Model::_skinProgram;
|
||||||
|
@ -86,6 +91,11 @@ Model::Locations Model::_specularMapLocations;
|
||||||
Model::Locations Model::_normalSpecularMapLocations;
|
Model::Locations Model::_normalSpecularMapLocations;
|
||||||
Model::Locations Model::_translucentLocations;
|
Model::Locations Model::_translucentLocations;
|
||||||
|
|
||||||
|
Model::Locations Model::_lightmapLocations;
|
||||||
|
Model::Locations Model::_lightmapNormalMapLocations;
|
||||||
|
Model::Locations Model::_lightmapSpecularMapLocations;
|
||||||
|
Model::Locations Model::_lightmapNormalSpecularMapLocations;
|
||||||
|
|
||||||
Model::SkinLocations Model::_skinLocations;
|
Model::SkinLocations Model::_skinLocations;
|
||||||
Model::SkinLocations Model::_skinNormalMapLocations;
|
Model::SkinLocations Model::_skinNormalMapLocations;
|
||||||
Model::SkinLocations Model::_skinSpecularMapLocations;
|
Model::SkinLocations Model::_skinSpecularMapLocations;
|
||||||
|
@ -140,17 +150,42 @@ void Model::initProgram(ProgramObject& program, Model::Locations& locations, int
|
||||||
|
|
||||||
glBindAttribLocation(program.programId(), gpu::Stream::TANGENT, "tangent");
|
glBindAttribLocation(program.programId(), gpu::Stream::TANGENT, "tangent");
|
||||||
|
|
||||||
|
glBindAttribLocation(program.programId(), gpu::Stream::TEXCOORD1, "texcoord1");
|
||||||
|
|
||||||
glLinkProgram(program.programId());
|
glLinkProgram(program.programId());
|
||||||
|
|
||||||
locations.tangent = program.attributeLocation("tangent");
|
locations.tangent = program.attributeLocation("tangent");
|
||||||
|
|
||||||
locations.alphaThreshold = program.uniformLocation("alphaThreshold");
|
locations.alphaThreshold = program.uniformLocation("alphaThreshold");
|
||||||
|
|
||||||
|
locations.texcoordMatrices = program.uniformLocation("texcoordMatrices");
|
||||||
|
|
||||||
|
locations.emissiveParams = program.uniformLocation("emissiveParams");
|
||||||
|
|
||||||
|
|
||||||
program.setUniformValue("diffuseMap", 0);
|
program.setUniformValue("diffuseMap", 0);
|
||||||
|
|
||||||
program.setUniformValue("normalMap", 1);
|
program.setUniformValue("normalMap", 1);
|
||||||
|
|
||||||
program.setUniformValue("specularMap", specularTextureUnit);
|
int loc = program.uniformLocation("specularMap");
|
||||||
|
if (loc >= 0) {
|
||||||
|
program.setUniformValue("specularMap", 2);
|
||||||
|
locations.specularTextureUnit = 2;
|
||||||
|
} else {
|
||||||
|
locations.specularTextureUnit = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
loc = program.uniformLocation("emissiveMap");
|
||||||
|
if (loc >= 0) {
|
||||||
|
program.setUniformValue("emissiveMap", 3);
|
||||||
|
locations.emissiveTextureUnit = 3;
|
||||||
|
} else {
|
||||||
|
locations.emissiveTextureUnit = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!program.isLinked()) {
|
||||||
|
program.release();
|
||||||
|
}
|
||||||
|
|
||||||
program.release();
|
program.release();
|
||||||
|
|
||||||
|
@ -268,6 +303,39 @@ void Model::init() {
|
||||||
_translucentProgram.link();
|
_translucentProgram.link();
|
||||||
|
|
||||||
initProgram(_translucentProgram, _translucentLocations);
|
initProgram(_translucentProgram, _translucentLocations);
|
||||||
|
|
||||||
|
// Lightmap
|
||||||
|
_lightmapProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_lightmap.vert");
|
||||||
|
_lightmapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/model_lightmap.frag");
|
||||||
|
_lightmapProgram.link();
|
||||||
|
|
||||||
|
initProgram(_lightmapProgram, _lightmapLocations);
|
||||||
|
|
||||||
|
_lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||||
|
Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert");
|
||||||
|
_lightmapNormalMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||||
|
Application::resourcesPath() + "shaders/model_lightmap_normal_map.frag");
|
||||||
|
_lightmapNormalMapProgram.link();
|
||||||
|
|
||||||
|
initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations);
|
||||||
|
|
||||||
|
_lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||||
|
Application::resourcesPath() + "shaders/model_lightmap.vert");
|
||||||
|
_lightmapSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||||
|
Application::resourcesPath() + "shaders/model_lightmap_specular_map.frag");
|
||||||
|
_lightmapSpecularMapProgram.link();
|
||||||
|
|
||||||
|
initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations);
|
||||||
|
|
||||||
|
_lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Vertex,
|
||||||
|
Application::resourcesPath() + "shaders/model_lightmap_normal_map.vert");
|
||||||
|
_lightmapNormalSpecularMapProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||||
|
Application::resourcesPath() + "shaders/model_lightmap_normal_specular_map.frag");
|
||||||
|
_lightmapNormalSpecularMapProgram.link();
|
||||||
|
|
||||||
|
initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations, 2);
|
||||||
|
// end lightmap
|
||||||
|
|
||||||
|
|
||||||
_shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert");
|
_shadowProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/model_shadow.vert");
|
||||||
_shadowProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
_shadowProgram.addShaderFromSourceFile(QGLShader::Fragment,
|
||||||
|
@ -621,14 +689,19 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
|
|
||||||
//renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args);
|
//renderMeshes(RenderMode mode, bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, book isSkinned, args);
|
||||||
int opaqueMeshPartsRendered = 0;
|
int opaqueMeshPartsRendered = 0;
|
||||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args);
|
||||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args);
|
||||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args);
|
||||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args);
|
||||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args);
|
||||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args);
|
||||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args);
|
||||||
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args);
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args);
|
||||||
|
|
||||||
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args);
|
||||||
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args);
|
||||||
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args);
|
||||||
|
opaqueMeshPartsRendered += renderMeshes(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args);
|
||||||
|
|
||||||
// render translucent meshes afterwards
|
// render translucent meshes afterwards
|
||||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||||
|
@ -642,14 +715,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
|
|
||||||
int translucentMeshPartsRendered = 0;
|
int translucentMeshPartsRendered = 0;
|
||||||
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
|
||||||
|
|
||||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||||
GLBATCH(glEnable)(GL_BLEND);
|
GLBATCH(glEnable)(GL_BLEND);
|
||||||
|
@ -666,14 +739,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
|
||||||
|
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args);
|
||||||
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args);
|
translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLBATCH(glDepthMask)(true);
|
GLBATCH(glDepthMask)(true);
|
||||||
|
@ -1562,15 +1635,20 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
int opaqueMeshPartsRendered = 0;
|
int opaqueMeshPartsRendered = 0;
|
||||||
|
|
||||||
// now, for each model in the scene, render the mesh portions
|
// now, for each model in the scene, render the mesh portions
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, false, args);
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, false, true, args);
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, false, args);
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, false, true, true, args);
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, false, args);
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, false, true, args);
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, false, args);
|
||||||
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, args);
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, false, true, true, true, args);
|
||||||
|
|
||||||
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, false, false, args);
|
||||||
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, false, true, false, args);
|
||||||
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, false, false, args);
|
||||||
|
opaqueMeshPartsRendered += renderMeshesForModelsInScene(batch, mode, false, DEFAULT_ALPHA_THRESHOLD, true, true, true, false, args);
|
||||||
|
|
||||||
// render translucent meshes afterwards
|
// render translucent meshes afterwards
|
||||||
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
//Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(false, true, true);
|
||||||
{
|
{
|
||||||
|
@ -1583,15 +1661,15 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
|
|
||||||
int translucentParts = 0;
|
int translucentParts = 0;
|
||||||
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
const float MOSTLY_OPAQUE_THRESHOLD = 0.75f;
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, false, true, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, false, true, true, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, false, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, false, true, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, true, true, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args);
|
||||||
|
|
||||||
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
GLBATCH(glDisable)(GL_ALPHA_TEST);
|
||||||
GLBATCH(glEnable)(GL_BLEND);
|
GLBATCH(glEnable)(GL_BLEND);
|
||||||
GLBATCH(glDepthMask)(false);
|
GLBATCH(glDepthMask)(false);
|
||||||
|
@ -1607,14 +1685,14 @@ void Model::endScene(RenderMode mode, RenderArgs* args) {
|
||||||
|
|
||||||
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) {
|
||||||
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f;
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, true, true, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, false, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, false, true, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, false, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, false, args);
|
||||||
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, true, true, true, args);
|
translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLBATCH(glDepthMask)(true);
|
GLBATCH(glDepthMask)(true);
|
||||||
|
@ -1689,7 +1767,12 @@ void Model::segregateMeshGroups() {
|
||||||
_meshesOpaqueSkinned.clear();
|
_meshesOpaqueSkinned.clear();
|
||||||
_meshesOpaqueTangentsSpecularSkinned.clear();
|
_meshesOpaqueTangentsSpecularSkinned.clear();
|
||||||
_meshesOpaqueSpecularSkinned.clear();
|
_meshesOpaqueSpecularSkinned.clear();
|
||||||
|
|
||||||
|
_meshesOpaqueLightmapTangents.clear();
|
||||||
|
_meshesOpaqueLightmap.clear();
|
||||||
|
_meshesOpaqueLightmapTangentsSpecular.clear();
|
||||||
|
_meshesOpaqueLightmapSpecular.clear();
|
||||||
|
|
||||||
_unsortedMeshesTranslucentTangents.clear();
|
_unsortedMeshesTranslucentTangents.clear();
|
||||||
_unsortedMeshesTranslucent.clear();
|
_unsortedMeshesTranslucent.clear();
|
||||||
_unsortedMeshesTranslucentTangentsSpecular.clear();
|
_unsortedMeshesTranslucentTangentsSpecular.clear();
|
||||||
|
@ -1710,6 +1793,11 @@ void Model::segregateMeshGroups() {
|
||||||
_unsortedMeshesOpaqueTangentsSpecularSkinned.clear();
|
_unsortedMeshesOpaqueTangentsSpecularSkinned.clear();
|
||||||
_unsortedMeshesOpaqueSpecularSkinned.clear();
|
_unsortedMeshesOpaqueSpecularSkinned.clear();
|
||||||
|
|
||||||
|
_unsortedMeshesOpaqueLightmapTangents.clear();
|
||||||
|
_unsortedMeshesOpaqueLightmap.clear();
|
||||||
|
_unsortedMeshesOpaqueLightmapTangentsSpecular.clear();
|
||||||
|
_unsortedMeshesOpaqueLightmapSpecular.clear();
|
||||||
|
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
const QVector<NetworkMesh>& networkMeshes = _geometry->getMeshes();
|
||||||
|
|
||||||
|
@ -1723,6 +1811,7 @@ void Model::segregateMeshGroups() {
|
||||||
bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size();
|
bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size();
|
||||||
bool hasTangents = !mesh.tangents.isEmpty();
|
bool hasTangents = !mesh.tangents.isEmpty();
|
||||||
bool hasSpecular = mesh.hasSpecularTexture();
|
bool hasSpecular = mesh.hasSpecularTexture();
|
||||||
|
bool hasLightmap = mesh.hasEmissiveTexture();
|
||||||
bool isSkinned = state.clusterMatrices.size() > 1;
|
bool isSkinned = state.clusterMatrices.size() > 1;
|
||||||
QString materialID;
|
QString materialID;
|
||||||
|
|
||||||
|
@ -1741,71 +1830,93 @@ void Model::segregateMeshGroups() {
|
||||||
qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size();
|
qDebug() << "materialID:" << materialID << "parts:" << mesh.parts.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) {
|
if (!hasLightmap) {
|
||||||
|
if (translucentMesh && !hasTangents && !hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesTranslucent.insertMulti(materialID, i);
|
_unsortedMeshesTranslucent.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) {
|
} else if (translucentMesh && hasTangents && !hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesTranslucentTangents.insertMulti(materialID, i);
|
_unsortedMeshesTranslucentTangents.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) {
|
} else if (translucentMesh && hasTangents && hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i);
|
_unsortedMeshesTranslucentTangentsSpecular.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) {
|
} else if (translucentMesh && !hasTangents && hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesTranslucentSpecular.insertMulti(materialID, i);
|
_unsortedMeshesTranslucentSpecular.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) {
|
} else if (translucentMesh && hasTangents && !hasSpecular && isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i);
|
_unsortedMeshesTranslucentTangentsSkinned.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) {
|
} else if (translucentMesh && !hasTangents && !hasSpecular && isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesTranslucentSkinned.insertMulti(materialID, i);
|
_unsortedMeshesTranslucentSkinned.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (translucentMesh && hasTangents && hasSpecular && isSkinned) {
|
} else if (translucentMesh && hasTangents && hasSpecular && isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i);
|
_unsortedMeshesTranslucentTangentsSpecularSkinned.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) {
|
} else if (translucentMesh && !hasTangents && hasSpecular && isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i);
|
_unsortedMeshesTranslucentSpecularSkinned.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) {
|
} else if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesOpaque.insertMulti(materialID, i);
|
_unsortedMeshesOpaque.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) {
|
} else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesOpaqueTangents.insertMulti(materialID, i);
|
_unsortedMeshesOpaqueTangents.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) {
|
} else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i);
|
_unsortedMeshesOpaqueTangentsSpecular.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) {
|
} else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesOpaqueSpecular.insertMulti(materialID, i);
|
_unsortedMeshesOpaqueSpecular.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) {
|
} else if (!translucentMesh && hasTangents && !hasSpecular && isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i);
|
_unsortedMeshesOpaqueTangentsSkinned.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) {
|
} else if (!translucentMesh && !hasTangents && !hasSpecular && isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesOpaqueSkinned.insertMulti(materialID, i);
|
_unsortedMeshesOpaqueSkinned.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) {
|
} else if (!translucentMesh && hasTangents && hasSpecular && isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i);
|
_unsortedMeshesOpaqueTangentsSpecularSkinned.insertMulti(materialID, i);
|
||||||
|
|
||||||
} else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) {
|
} else if (!translucentMesh && !hasTangents && hasSpecular && isSkinned) {
|
||||||
|
|
||||||
_unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i);
|
_unsortedMeshesOpaqueSpecularSkinned.insertMulti(materialID, i);
|
||||||
|
} else {
|
||||||
|
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
|
if (!translucentMesh && !hasTangents && !hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
|
_unsortedMeshesOpaqueLightmap.insertMulti(materialID, i);
|
||||||
|
|
||||||
|
} else if (!translucentMesh && hasTangents && !hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
|
_unsortedMeshesOpaqueLightmapTangents.insertMulti(materialID, i);
|
||||||
|
|
||||||
|
} else if (!translucentMesh && hasTangents && hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
|
_unsortedMeshesOpaqueLightmapTangentsSpecular.insertMulti(materialID, i);
|
||||||
|
|
||||||
|
} else if (!translucentMesh && !hasTangents && hasSpecular && !isSkinned) {
|
||||||
|
|
||||||
|
_unsortedMeshesOpaqueLightmapSpecular.insertMulti(materialID, i);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1873,6 +1984,22 @@ void Model::segregateMeshGroups() {
|
||||||
_meshesOpaqueSpecularSkinned.append(i);
|
_meshesOpaqueSpecularSkinned.append(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach(int i, _unsortedMeshesOpaqueLightmap) {
|
||||||
|
_meshesOpaqueLightmap.append(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(int i, _unsortedMeshesOpaqueLightmapTangents) {
|
||||||
|
_meshesOpaqueLightmapTangents.append(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(int i, _unsortedMeshesOpaqueLightmapTangentsSpecular) {
|
||||||
|
_meshesOpaqueLightmapTangentsSpecular.append(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(int i, _unsortedMeshesOpaqueLightmapSpecular) {
|
||||||
|
_meshesOpaqueLightmapSpecular.append(i);
|
||||||
|
}
|
||||||
|
|
||||||
_unsortedMeshesTranslucentTangents.clear();
|
_unsortedMeshesTranslucentTangents.clear();
|
||||||
_unsortedMeshesTranslucent.clear();
|
_unsortedMeshesTranslucent.clear();
|
||||||
_unsortedMeshesTranslucentTangentsSpecular.clear();
|
_unsortedMeshesTranslucentTangentsSpecular.clear();
|
||||||
|
@ -1893,10 +2020,15 @@ void Model::segregateMeshGroups() {
|
||||||
_unsortedMeshesOpaqueTangentsSpecularSkinned.clear();
|
_unsortedMeshesOpaqueTangentsSpecularSkinned.clear();
|
||||||
_unsortedMeshesOpaqueSpecularSkinned.clear();
|
_unsortedMeshesOpaqueSpecularSkinned.clear();
|
||||||
|
|
||||||
|
_unsortedMeshesOpaqueLightmapTangents.clear();
|
||||||
|
_unsortedMeshesOpaqueLightmap.clear();
|
||||||
|
_unsortedMeshesOpaqueLightmapTangentsSpecular.clear();
|
||||||
|
_unsortedMeshesOpaqueLightmapSpecular.clear();
|
||||||
|
|
||||||
_meshGroupsKnown = true;
|
_meshGroupsKnown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned) {
|
QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
|
|
||||||
// depending on which parameters we were called with, pick the correct mesh group to render
|
// depending on which parameters we were called with, pick the correct mesh group to render
|
||||||
|
@ -1917,22 +2049,33 @@ QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool h
|
||||||
whichList = &_meshesTranslucentTangentsSpecularSkinned;
|
whichList = &_meshesTranslucentTangentsSpecularSkinned;
|
||||||
} else if (translucent && !hasTangents && hasSpecular && isSkinned) {
|
} else if (translucent && !hasTangents && hasSpecular && isSkinned) {
|
||||||
whichList = &_meshesTranslucentSpecularSkinned;
|
whichList = &_meshesTranslucentSpecularSkinned;
|
||||||
} else if (!translucent && !hasTangents && !hasSpecular && !isSkinned) {
|
|
||||||
|
} else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && !isSkinned) {
|
||||||
whichList = &_meshesOpaque;
|
whichList = &_meshesOpaque;
|
||||||
} else if (!translucent && hasTangents && !hasSpecular && !isSkinned) {
|
} else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && !isSkinned) {
|
||||||
whichList = &_meshesOpaqueTangents;
|
whichList = &_meshesOpaqueTangents;
|
||||||
} else if (!translucent && hasTangents && hasSpecular && !isSkinned) {
|
} else if (!translucent && !hasLightmap && hasTangents && hasSpecular && !isSkinned) {
|
||||||
whichList = &_meshesOpaqueTangentsSpecular;
|
whichList = &_meshesOpaqueTangentsSpecular;
|
||||||
} else if (!translucent && !hasTangents && hasSpecular && !isSkinned) {
|
} else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && !isSkinned) {
|
||||||
whichList = &_meshesOpaqueSpecular;
|
whichList = &_meshesOpaqueSpecular;
|
||||||
} else if (!translucent && hasTangents && !hasSpecular && isSkinned) {
|
} else if (!translucent && !hasLightmap && hasTangents && !hasSpecular && isSkinned) {
|
||||||
whichList = &_meshesOpaqueTangentsSkinned;
|
whichList = &_meshesOpaqueTangentsSkinned;
|
||||||
} else if (!translucent && !hasTangents && !hasSpecular && isSkinned) {
|
} else if (!translucent && !hasLightmap && !hasTangents && !hasSpecular && isSkinned) {
|
||||||
whichList = &_meshesOpaqueSkinned;
|
whichList = &_meshesOpaqueSkinned;
|
||||||
} else if (!translucent && hasTangents && hasSpecular && isSkinned) {
|
} else if (!translucent && !hasLightmap && hasTangents && hasSpecular && isSkinned) {
|
||||||
whichList = &_meshesOpaqueTangentsSpecularSkinned;
|
whichList = &_meshesOpaqueTangentsSpecularSkinned;
|
||||||
} else if (!translucent && !hasTangents && hasSpecular && isSkinned) {
|
} else if (!translucent && !hasLightmap && !hasTangents && hasSpecular && isSkinned) {
|
||||||
whichList = &_meshesOpaqueSpecularSkinned;
|
whichList = &_meshesOpaqueSpecularSkinned;
|
||||||
|
|
||||||
|
} else if (!translucent && hasLightmap && !hasTangents && !hasSpecular && !isSkinned) {
|
||||||
|
whichList = &_meshesOpaqueLightmap;
|
||||||
|
} else if (!translucent && hasLightmap && hasTangents && !hasSpecular && !isSkinned) {
|
||||||
|
whichList = &_meshesOpaqueLightmapTangents;
|
||||||
|
} else if (!translucent && hasLightmap && hasTangents && hasSpecular && !isSkinned) {
|
||||||
|
whichList = &_meshesOpaqueLightmapTangentsSpecular;
|
||||||
|
} else if (!translucent && hasLightmap && !hasTangents && hasSpecular && !isSkinned) {
|
||||||
|
whichList = &_meshesOpaqueLightmapSpecular;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
|
qDebug() << "unexpected!!! this mesh didn't fall into any or our groups???";
|
||||||
}
|
}
|
||||||
|
@ -1940,14 +2083,13 @@ QVector<int>* Model::pickMeshList(bool translucent, float alphaThreshold, bool h
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
||||||
SkinLocations*& skinLocations, GLenum& specularTextureUnit) {
|
Locations*& locations, SkinLocations*& skinLocations) {
|
||||||
|
|
||||||
ProgramObject* program = &_program;
|
ProgramObject* program = &_program;
|
||||||
Locations* locations = &_locations;
|
locations = &_locations;
|
||||||
ProgramObject* skinProgram = &_skinProgram;
|
ProgramObject* skinProgram = &_skinProgram;
|
||||||
skinLocations = &_skinLocations;
|
skinLocations = &_skinLocations;
|
||||||
specularTextureUnit = 0;
|
|
||||||
if (mode == SHADOW_RENDER_MODE) {
|
if (mode == SHADOW_RENDER_MODE) {
|
||||||
program = &_shadowProgram;
|
program = &_shadowProgram;
|
||||||
skinProgram = &_skinShadowProgram;
|
skinProgram = &_skinShadowProgram;
|
||||||
|
@ -1958,33 +2100,58 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
|
||||||
skinProgram = &_skinTranslucentProgram;
|
skinProgram = &_skinTranslucentProgram;
|
||||||
skinLocations = &_skinTranslucentLocations;
|
skinLocations = &_skinTranslucentLocations;
|
||||||
|
|
||||||
} else if (hasTangents) {
|
} else if (hasLightmap) {
|
||||||
if (hasSpecular) {
|
if (hasTangents) {
|
||||||
program = &_normalSpecularMapProgram;
|
if (hasSpecular) {
|
||||||
locations = &_normalSpecularMapLocations;
|
program = &_lightmapNormalSpecularMapProgram;
|
||||||
skinProgram = &_skinNormalSpecularMapProgram;
|
locations = &_lightmapNormalSpecularMapLocations;
|
||||||
skinLocations = &_skinNormalSpecularMapLocations;
|
skinProgram = NULL;
|
||||||
specularTextureUnit = GL_TEXTURE2;
|
skinLocations = NULL;
|
||||||
|
} else {
|
||||||
|
program = &_lightmapNormalMapProgram;
|
||||||
|
locations = &_lightmapNormalMapLocations;
|
||||||
|
skinProgram = NULL;
|
||||||
|
skinLocations = NULL;
|
||||||
|
}
|
||||||
|
} else if (hasSpecular) {
|
||||||
|
program = &_lightmapSpecularMapProgram;
|
||||||
|
locations = &_lightmapSpecularMapLocations;
|
||||||
|
skinProgram = NULL;
|
||||||
|
skinLocations = NULL;
|
||||||
} else {
|
} else {
|
||||||
program = &_normalMapProgram;
|
program = &_lightmapProgram;
|
||||||
locations = &_normalMapLocations;
|
locations = &_lightmapLocations;
|
||||||
skinProgram = &_skinNormalMapProgram;
|
skinProgram = NULL;
|
||||||
skinLocations = &_skinNormalMapLocations;
|
skinLocations = NULL;
|
||||||
}
|
}
|
||||||
} else if (hasSpecular) {
|
} else {
|
||||||
program = &_specularMapProgram;
|
if (hasTangents) {
|
||||||
locations = &_specularMapLocations;
|
if (hasSpecular) {
|
||||||
skinProgram = &_skinSpecularMapProgram;
|
program = &_normalSpecularMapProgram;
|
||||||
skinLocations = &_skinSpecularMapLocations;
|
locations = &_normalSpecularMapLocations;
|
||||||
specularTextureUnit = GL_TEXTURE1;
|
skinProgram = &_skinNormalSpecularMapProgram;
|
||||||
}
|
skinLocations = &_skinNormalSpecularMapLocations;
|
||||||
|
} else {
|
||||||
|
program = &_normalMapProgram;
|
||||||
|
locations = &_normalMapLocations;
|
||||||
|
skinProgram = &_skinNormalMapProgram;
|
||||||
|
skinLocations = &_skinNormalMapLocations;
|
||||||
|
}
|
||||||
|
} else if (hasSpecular) {
|
||||||
|
program = &_specularMapProgram;
|
||||||
|
locations = &_specularMapLocations;
|
||||||
|
skinProgram = &_skinSpecularMapProgram;
|
||||||
|
skinLocations = &_skinSpecularMapLocations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ProgramObject* activeProgram = program;
|
ProgramObject* activeProgram = program;
|
||||||
Locations* activeLocations = locations;
|
Locations* activeLocations = locations;
|
||||||
|
|
||||||
if (isSkinned) {
|
if (isSkinned) {
|
||||||
activeProgram = skinProgram;
|
activeProgram = skinProgram;
|
||||||
activeLocations = skinLocations;
|
activeLocations = skinLocations;
|
||||||
|
locations = skinLocations;
|
||||||
}
|
}
|
||||||
// This code replace the "bind()" on the QGLProgram
|
// This code replace the "bind()" on the QGLProgram
|
||||||
if (!activeProgram->isLinked()) {
|
if (!activeProgram->isLinked()) {
|
||||||
|
@ -1996,26 +2163,26 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f
|
||||||
}
|
}
|
||||||
|
|
||||||
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
|
||||||
|
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
int meshPartsRendered = 0;
|
int meshPartsRendered = 0;
|
||||||
|
|
||||||
bool pickProgramsNeeded = true;
|
bool pickProgramsNeeded = true;
|
||||||
|
Locations* locations;
|
||||||
SkinLocations* skinLocations;
|
SkinLocations* skinLocations;
|
||||||
GLenum specularTextureUnit;
|
|
||||||
|
|
||||||
foreach(Model* model, _modelsInScene) {
|
foreach(Model* model, _modelsInScene) {
|
||||||
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned);
|
QVector<int>* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
||||||
if (whichList) {
|
if (whichList) {
|
||||||
QVector<int>& list = *whichList;
|
QVector<int>& list = *whichList;
|
||||||
if (list.size() > 0) {
|
if (list.size() > 0) {
|
||||||
if (pickProgramsNeeded) {
|
if (pickProgramsNeeded) {
|
||||||
pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit);
|
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations);
|
||||||
pickProgramsNeeded = false;
|
pickProgramsNeeded = false;
|
||||||
}
|
}
|
||||||
model->setupBatchTransform(batch);
|
model->setupBatchTransform(batch);
|
||||||
meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit);
|
meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations);
|
||||||
GLBATCH(glPopMatrix)();
|
GLBATCH(glPopMatrix)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2028,12 +2195,12 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args) {
|
||||||
|
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
int meshPartsRendered = 0;
|
int meshPartsRendered = 0;
|
||||||
|
|
||||||
QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned);
|
QVector<int>* whichList = pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned);
|
||||||
|
|
||||||
if (!whichList) {
|
if (!whichList) {
|
||||||
qDebug() << "unexpected!!! we don't know which list of meshes to render...";
|
qDebug() << "unexpected!!! we don't know which list of meshes to render...";
|
||||||
|
@ -2046,10 +2213,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Locations* locations;
|
||||||
SkinLocations* skinLocations;
|
SkinLocations* skinLocations;
|
||||||
GLenum specularTextureUnit;
|
pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations);
|
||||||
pickPrograms(batch, mode, translucent, alphaThreshold, hasTangents, hasSpecular, isSkinned, args, skinLocations, specularTextureUnit);
|
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations);
|
||||||
meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, skinLocations, specularTextureUnit);
|
|
||||||
GLBATCH(glUseProgram)(0);
|
GLBATCH(glUseProgram)(0);
|
||||||
|
|
||||||
return meshPartsRendered;
|
return meshPartsRendered;
|
||||||
|
@ -2057,7 +2224,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
|
||||||
|
|
||||||
|
|
||||||
int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args,
|
int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args,
|
||||||
SkinLocations* skinLocations, GLenum specularTextureUnit) {
|
Locations* locations, SkinLocations* skinLocations) {
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
|
bool dontCullOutOfViewMeshParts = Menu::getInstance()->isOptionChecked(MenuOption::DontCullOutOfViewMeshParts);
|
||||||
bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts);
|
bool cullTooSmallMeshParts = !Menu::getInstance()->isOptionChecked(MenuOption::DontCullTooSmallMeshParts);
|
||||||
|
@ -2174,7 +2341,7 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse);
|
GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse);
|
||||||
GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular);
|
GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular);
|
||||||
GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.0f ? 128.0f: part.shininess));
|
GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.0f ? 128.0f: part.shininess));
|
||||||
|
|
||||||
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
||||||
if (mesh.isEye && diffuseMap) {
|
if (mesh.isEye && diffuseMap) {
|
||||||
diffuseMap = (_dilatedTextures[i][j] =
|
diffuseMap = (_dilatedTextures[i][j] =
|
||||||
|
@ -2182,7 +2349,18 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
}
|
}
|
||||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ?
|
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !diffuseMap ?
|
||||||
Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID());
|
Application::getInstance()->getTextureCache()->getWhiteTextureID() : diffuseMap->getID());
|
||||||
|
|
||||||
|
if (locations->texcoordMatrices >= 0) {
|
||||||
|
glm::mat4 texcoordTransform[2];
|
||||||
|
if (!part.diffuseTexture.transform.isIdentity()) {
|
||||||
|
part.diffuseTexture.transform.getMatrix(texcoordTransform[0]);
|
||||||
|
}
|
||||||
|
if (!part.emissiveTexture.transform.isIdentity()) {
|
||||||
|
part.emissiveTexture.transform.getMatrix(texcoordTransform[1]);
|
||||||
|
}
|
||||||
|
GLBATCH(glUniformMatrix4fv)(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform);
|
||||||
|
}
|
||||||
|
|
||||||
if (!mesh.tangents.isEmpty()) {
|
if (!mesh.tangents.isEmpty()) {
|
||||||
GLBATCH(glActiveTexture)(GL_TEXTURE1);
|
GLBATCH(glActiveTexture)(GL_TEXTURE1);
|
||||||
Texture* normalMap = networkPart.normalTexture.data();
|
Texture* normalMap = networkPart.normalTexture.data();
|
||||||
|
@ -2191,13 +2369,25 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (specularTextureUnit) {
|
if (locations->specularTextureUnit >= 0) {
|
||||||
GLBATCH(glActiveTexture)(specularTextureUnit);
|
GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit);
|
||||||
Texture* specularMap = networkPart.specularTexture.data();
|
Texture* specularMap = networkPart.specularTexture.data();
|
||||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ?
|
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !specularMap ?
|
||||||
Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID());
|
Application::getInstance()->getTextureCache()->getWhiteTextureID() : specularMap->getID());
|
||||||
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (locations->emissiveTextureUnit >= 0) {
|
||||||
|
assert(locations->emissiveParams >= 0); // we should have the emissiveParams defined in the shader
|
||||||
|
GLBATCH(glUniform2f)(locations->emissiveParams, 0.1f, 4.0f);
|
||||||
|
|
||||||
|
GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit);
|
||||||
|
Texture* emissiveMap = networkPart.emissiveTexture.data();
|
||||||
|
GLBATCH(glBindTexture)(GL_TEXTURE_2D, !emissiveMap ?
|
||||||
|
Application::getInstance()->getTextureCache()->getWhiteTextureID() : emissiveMap->getID());
|
||||||
|
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
|
||||||
if (args) {
|
if (args) {
|
||||||
args->_materialSwitches++;
|
args->_materialSwitches++;
|
||||||
}
|
}
|
||||||
|
@ -2232,8 +2422,14 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
||||||
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (specularTextureUnit) {
|
if (locations->specularTextureUnit >= 0) {
|
||||||
GLBATCH(glActiveTexture)(specularTextureUnit);
|
GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->specularTextureUnit);
|
||||||
|
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||||
|
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locations->emissiveTextureUnit >= 0) {
|
||||||
|
GLBATCH(glActiveTexture)(GL_TEXTURE0 + locations->emissiveTextureUnit);
|
||||||
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0);
|
||||||
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
GLBATCH(glActiveTexture)(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,7 +303,12 @@ private:
|
||||||
static ProgramObject _specularMapProgram;
|
static ProgramObject _specularMapProgram;
|
||||||
static ProgramObject _normalSpecularMapProgram;
|
static ProgramObject _normalSpecularMapProgram;
|
||||||
static ProgramObject _translucentProgram;
|
static ProgramObject _translucentProgram;
|
||||||
|
|
||||||
|
static ProgramObject _lightmapProgram;
|
||||||
|
static ProgramObject _lightmapNormalMapProgram;
|
||||||
|
static ProgramObject _lightmapSpecularMapProgram;
|
||||||
|
static ProgramObject _lightmapNormalSpecularMapProgram;
|
||||||
|
|
||||||
static ProgramObject _shadowProgram;
|
static ProgramObject _shadowProgram;
|
||||||
|
|
||||||
static ProgramObject _skinProgram;
|
static ProgramObject _skinProgram;
|
||||||
|
@ -311,7 +316,7 @@ private:
|
||||||
static ProgramObject _skinSpecularMapProgram;
|
static ProgramObject _skinSpecularMapProgram;
|
||||||
static ProgramObject _skinNormalSpecularMapProgram;
|
static ProgramObject _skinNormalSpecularMapProgram;
|
||||||
static ProgramObject _skinTranslucentProgram;
|
static ProgramObject _skinTranslucentProgram;
|
||||||
|
|
||||||
static ProgramObject _skinShadowProgram;
|
static ProgramObject _skinShadowProgram;
|
||||||
|
|
||||||
static int _normalMapTangentLocation;
|
static int _normalMapTangentLocation;
|
||||||
|
@ -321,6 +326,10 @@ private:
|
||||||
public:
|
public:
|
||||||
int tangent;
|
int tangent;
|
||||||
int alphaThreshold;
|
int alphaThreshold;
|
||||||
|
int texcoordMatrices;
|
||||||
|
int specularTextureUnit;
|
||||||
|
int emissiveTextureUnit;
|
||||||
|
int emissiveParams;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Locations _locations;
|
static Locations _locations;
|
||||||
|
@ -328,6 +337,11 @@ private:
|
||||||
static Locations _specularMapLocations;
|
static Locations _specularMapLocations;
|
||||||
static Locations _normalSpecularMapLocations;
|
static Locations _normalSpecularMapLocations;
|
||||||
static Locations _translucentLocations;
|
static Locations _translucentLocations;
|
||||||
|
|
||||||
|
static Locations _lightmapLocations;
|
||||||
|
static Locations _lightmapNormalMapLocations;
|
||||||
|
static Locations _lightmapSpecularMapLocations;
|
||||||
|
static Locations _lightmapNormalSpecularMapLocations;
|
||||||
|
|
||||||
static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1);
|
static void initProgram(ProgramObject& program, Locations& locations, int specularTextureUnit = 1);
|
||||||
|
|
||||||
|
@ -335,7 +349,7 @@ private:
|
||||||
public:
|
public:
|
||||||
int clusterMatrices;
|
int clusterMatrices;
|
||||||
int clusterIndices;
|
int clusterIndices;
|
||||||
int clusterWeights;
|
int clusterWeights;
|
||||||
};
|
};
|
||||||
|
|
||||||
static SkinLocations _skinLocations;
|
static SkinLocations _skinLocations;
|
||||||
|
@ -344,7 +358,7 @@ private:
|
||||||
static SkinLocations _skinNormalSpecularMapLocations;
|
static SkinLocations _skinNormalSpecularMapLocations;
|
||||||
static SkinLocations _skinShadowLocations;
|
static SkinLocations _skinShadowLocations;
|
||||||
static SkinLocations _skinTranslucentLocations;
|
static SkinLocations _skinTranslucentLocations;
|
||||||
|
|
||||||
static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1);
|
static void initSkinProgram(ProgramObject& program, SkinLocations& locations, int specularTextureUnit = 1);
|
||||||
|
|
||||||
QVector<AABox> _calculatedMeshBoxes;
|
QVector<AABox> _calculatedMeshBoxes;
|
||||||
|
@ -376,6 +390,11 @@ private:
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueTangentsSpecularSkinned;
|
QMap<QString, int> _unsortedMeshesOpaqueTangentsSpecularSkinned;
|
||||||
QMap<QString, int> _unsortedMeshesOpaqueSpecularSkinned;
|
QMap<QString, int> _unsortedMeshesOpaqueSpecularSkinned;
|
||||||
|
|
||||||
|
QMap<QString, int> _unsortedMeshesOpaqueLightmap;
|
||||||
|
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangents;
|
||||||
|
QMap<QString, int> _unsortedMeshesOpaqueLightmapTangentsSpecular;
|
||||||
|
QMap<QString, int> _unsortedMeshesOpaqueLightmapSpecular;
|
||||||
|
|
||||||
QVector<int> _meshesTranslucent;
|
QVector<int> _meshesTranslucent;
|
||||||
QVector<int> _meshesTranslucentTangents;
|
QVector<int> _meshesTranslucentTangents;
|
||||||
QVector<int> _meshesTranslucentTangentsSpecular;
|
QVector<int> _meshesTranslucentTangentsSpecular;
|
||||||
|
@ -396,6 +415,12 @@ private:
|
||||||
QVector<int> _meshesOpaqueTangentsSpecularSkinned;
|
QVector<int> _meshesOpaqueTangentsSpecularSkinned;
|
||||||
QVector<int> _meshesOpaqueSpecularSkinned;
|
QVector<int> _meshesOpaqueSpecularSkinned;
|
||||||
|
|
||||||
|
QVector<int> _meshesOpaqueLightmap;
|
||||||
|
QVector<int> _meshesOpaqueLightmapTangents;
|
||||||
|
QVector<int> _meshesOpaqueLightmapTangentsSpecular;
|
||||||
|
QVector<int> _meshesOpaqueLightmapSpecular;
|
||||||
|
|
||||||
|
|
||||||
// Scene rendering support
|
// Scene rendering support
|
||||||
static QVector<Model*> _modelsInScene;
|
static QVector<Model*> _modelsInScene;
|
||||||
static gpu::Batch _sceneRenderBatch;
|
static gpu::Batch _sceneRenderBatch;
|
||||||
|
@ -407,19 +432,19 @@ private:
|
||||||
void renderSetup(RenderArgs* args);
|
void renderSetup(RenderArgs* args);
|
||||||
bool renderCore(float alpha, RenderMode mode, RenderArgs* args);
|
bool renderCore(float alpha, RenderMode mode, RenderArgs* args);
|
||||||
int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL);
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL);
|
||||||
void setupBatchTransform(gpu::Batch& batch);
|
void setupBatchTransform(gpu::Batch& batch);
|
||||||
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasTangents, bool hasSpecular, bool isSkinned);
|
QVector<int>* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned);
|
||||||
|
|
||||||
int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
int renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
RenderArgs* args, SkinLocations* skinLocations, GLenum specularTextureUnit);
|
RenderArgs* args, Locations* locations, SkinLocations* skinLocations);
|
||||||
|
|
||||||
static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args,
|
||||||
SkinLocations*& skinLocations, GLenum& specularTextureUnit);
|
Locations*& locations, SkinLocations*& skinLocations);
|
||||||
|
|
||||||
static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold,
|
||||||
bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args);
|
bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@ class NetworkTexture;
|
||||||
|
|
||||||
typedef QSharedPointer<NetworkTexture> NetworkTexturePointer;
|
typedef QSharedPointer<NetworkTexture> NetworkTexturePointer;
|
||||||
|
|
||||||
enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, SPLAT_TEXTURE };
|
enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, SPLAT_TEXTURE };
|
||||||
|
|
||||||
/// Stores cached textures, including render-to-texture targets.
|
/// Stores cached textures, including render-to-texture targets.
|
||||||
class TextureCache : public ResourceCache {
|
class TextureCache : public ResourceCache {
|
||||||
|
@ -67,7 +67,7 @@ public:
|
||||||
|
|
||||||
/// Returns the ID of the primary framebuffer object's specular texture.
|
/// Returns the ID of the primary framebuffer object's specular texture.
|
||||||
GLuint getPrimarySpecularTextureID();
|
GLuint getPrimarySpecularTextureID();
|
||||||
|
|
||||||
/// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound.
|
/// Enables or disables draw buffers on the primary framebuffer. Note: the primary framebuffer must be bound.
|
||||||
void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false);
|
void setPrimaryDrawBuffers(bool color, bool normal = false, bool specular = false);
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,54 @@
|
||||||
|
|
||||||
#include "FBXReader.h"
|
#include "FBXReader.h"
|
||||||
|
|
||||||
|
|
||||||
|
// TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems...
|
||||||
|
//#define DEBUG_FBXREADER
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
struct TextureParam {
|
||||||
|
glm::vec2 UVTranslation;
|
||||||
|
glm::vec2 UVScaling;
|
||||||
|
glm::vec4 cropping;
|
||||||
|
std::string UVSet;
|
||||||
|
|
||||||
|
glm::vec3 translation;
|
||||||
|
glm::vec3 rotation;
|
||||||
|
glm::vec3 scaling;
|
||||||
|
uint8_t alphaSource;
|
||||||
|
uint8_t currentTextureBlendMode;
|
||||||
|
bool useMaterial;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool assign(T& ref, const T& v) {
|
||||||
|
if (ref == v) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
ref = v;
|
||||||
|
isDefault = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDefault;
|
||||||
|
|
||||||
|
TextureParam() :
|
||||||
|
UVTranslation(0.0f),
|
||||||
|
UVScaling(1.0f),
|
||||||
|
cropping(0.0f),
|
||||||
|
UVSet("map1"),
|
||||||
|
translation(0.0f),
|
||||||
|
rotation(0.0f),
|
||||||
|
scaling(1.0f),
|
||||||
|
alphaSource(0),
|
||||||
|
currentTextureBlendMode(0),
|
||||||
|
useMaterial(true),
|
||||||
|
isDefault(true)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
bool FBXMesh::hasSpecularTexture() const {
|
bool FBXMesh::hasSpecularTexture() const {
|
||||||
foreach (const FBXMeshPart& part, parts) {
|
foreach (const FBXMeshPart& part, parts) {
|
||||||
if (!part.specularTexture.filename.isEmpty()) {
|
if (!part.specularTexture.filename.isEmpty()) {
|
||||||
|
@ -41,6 +87,15 @@ bool FBXMesh::hasSpecularTexture() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FBXMesh::hasEmissiveTexture() const {
|
||||||
|
foreach (const FBXMeshPart& part, parts) {
|
||||||
|
if (!part.emissiveTexture.filename.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList FBXGeometry::getJointNames() const {
|
QStringList FBXGeometry::getJointNames() const {
|
||||||
QStringList names;
|
QStringList names;
|
||||||
foreach (const FBXJoint& joint, joints) {
|
foreach (const FBXJoint& joint, joints) {
|
||||||
|
@ -709,6 +764,7 @@ class Vertex {
|
||||||
public:
|
public:
|
||||||
int originalIndex;
|
int originalIndex;
|
||||||
glm::vec2 texCoord;
|
glm::vec2 texCoord;
|
||||||
|
glm::vec2 texCoord1;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint qHash(const Vertex& vertex, uint seed = 0) {
|
uint qHash(const Vertex& vertex, uint seed = 0) {
|
||||||
|
@ -716,7 +772,7 @@ uint qHash(const Vertex& vertex, uint seed = 0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Vertex& v1, const Vertex& v2) {
|
bool operator==(const Vertex& v1, const Vertex& v2) {
|
||||||
return v1.originalIndex == v2.originalIndex && v1.texCoord == v2.texCoord;
|
return v1.originalIndex == v2.originalIndex && v1.texCoord == v2.texCoord && v1.texCoord1 == v2.texCoord1;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExtractedMesh {
|
class ExtractedMesh {
|
||||||
|
@ -725,6 +781,16 @@ public:
|
||||||
QMultiHash<int, int> newIndices;
|
QMultiHash<int, int> newIndices;
|
||||||
QVector<QHash<int, int> > blendshapeIndexMaps;
|
QVector<QHash<int, int> > blendshapeIndexMaps;
|
||||||
QVector<QPair<int, int> > partMaterialTextures;
|
QVector<QPair<int, int> > partMaterialTextures;
|
||||||
|
QHash<QString, int> texcoordSetMap;
|
||||||
|
std::map<std::string, int> texcoordSetMap2;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AttributeData {
|
||||||
|
public:
|
||||||
|
QVector<glm::vec2> texCoords;
|
||||||
|
QVector<int> texCoordIndices;
|
||||||
|
std::string name;
|
||||||
|
int index;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MeshData {
|
class MeshData {
|
||||||
|
@ -739,6 +805,8 @@ public:
|
||||||
QVector<int> texCoordIndices;
|
QVector<int> texCoordIndices;
|
||||||
|
|
||||||
QHash<Vertex, int> indices;
|
QHash<Vertex, int> indices;
|
||||||
|
|
||||||
|
std::vector<AttributeData> attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
||||||
|
@ -780,6 +848,20 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
||||||
vertex.texCoord = data.texCoords.at(texCoordIndex);
|
vertex.texCoord = data.texCoords.at(texCoordIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasMoreTexcoords = (data.attributes.size() > 1);
|
||||||
|
if (hasMoreTexcoords) {
|
||||||
|
if (data.attributes[1].texCoordIndices.empty()) {
|
||||||
|
if (index < data.attributes[1].texCoords.size()) {
|
||||||
|
vertex.texCoord1 = data.attributes[1].texCoords.at(index);
|
||||||
|
}
|
||||||
|
} else if (index < data.attributes[1].texCoordIndices.size()) {
|
||||||
|
int texCoordIndex = data.attributes[1].texCoordIndices.at(index);
|
||||||
|
if (texCoordIndex >= 0 && texCoordIndex < data.attributes[1].texCoords.size()) {
|
||||||
|
vertex.texCoord1 = data.attributes[1].texCoords.at(texCoordIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QHash<Vertex, int>::const_iterator it = data.indices.find(vertex);
|
QHash<Vertex, int>::const_iterator it = data.indices.find(vertex);
|
||||||
if (it == data.indices.constEnd()) {
|
if (it == data.indices.constEnd()) {
|
||||||
|
@ -790,7 +872,9 @@ void appendIndex(MeshData& data, QVector<int>& indices, int index) {
|
||||||
data.extracted.mesh.vertices.append(position);
|
data.extracted.mesh.vertices.append(position);
|
||||||
data.extracted.mesh.normals.append(normal);
|
data.extracted.mesh.normals.append(normal);
|
||||||
data.extracted.mesh.texCoords.append(vertex.texCoord);
|
data.extracted.mesh.texCoords.append(vertex.texCoord);
|
||||||
|
if (hasMoreTexcoords) {
|
||||||
|
data.extracted.mesh.texCoords1.append(vertex.texCoord1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
indices.append(*it);
|
indices.append(*it);
|
||||||
data.extracted.mesh.normals[*it] += normal;
|
data.extracted.mesh.normals[*it] += normal;
|
||||||
|
@ -829,13 +913,67 @@ ExtractedMesh extractMesh(const FBXNode& object) {
|
||||||
// hack to work around wacky Makehuman exports
|
// hack to work around wacky Makehuman exports
|
||||||
data.normalsByVertex = true;
|
data.normalsByVertex = true;
|
||||||
}
|
}
|
||||||
} else if (child.name == "LayerElementUV" && child.properties.at(0).toInt() == 0) {
|
} else if (child.name == "LayerElementUV") {
|
||||||
foreach (const FBXNode& subdata, child.children) {
|
if (child.properties.at(0).toInt() == 0) {
|
||||||
if (subdata.name == "UV") {
|
AttributeData attrib;
|
||||||
data.texCoords = createVec2Vector(getDoubleVector(subdata));
|
attrib.index = child.properties.at(0).toInt();
|
||||||
|
foreach (const FBXNode& subdata, child.children) {
|
||||||
|
if (subdata.name == "UV") {
|
||||||
|
data.texCoords = createVec2Vector(getDoubleVector(subdata));
|
||||||
|
attrib.texCoords = createVec2Vector(getDoubleVector(subdata));
|
||||||
|
} else if (subdata.name == "UVIndex") {
|
||||||
|
data.texCoordIndices = getIntVector(subdata);
|
||||||
|
attrib.texCoordIndices = getIntVector(subdata);
|
||||||
|
} else if (subdata.name == "Name") {
|
||||||
|
attrib.name = subdata.properties.at(0).toString().toStdString();
|
||||||
|
}
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
else {
|
||||||
|
int unknown = 0;
|
||||||
|
std::string subname = subdata.name.data();
|
||||||
|
if ( (subdata.name == "Version")
|
||||||
|
|| (subdata.name == "MappingInformationType")
|
||||||
|
|| (subdata.name == "ReferenceInformationType") ) {
|
||||||
|
} else {
|
||||||
|
unknown++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size());
|
||||||
|
data.attributes.push_back(attrib);
|
||||||
|
} else {
|
||||||
|
AttributeData attrib;
|
||||||
|
attrib.index = child.properties.at(0).toInt();
|
||||||
|
foreach (const FBXNode& subdata, child.children) {
|
||||||
|
if (subdata.name == "UV") {
|
||||||
|
attrib.texCoords = createVec2Vector(getDoubleVector(subdata));
|
||||||
|
} else if (subdata.name == "UVIndex") {
|
||||||
|
attrib.texCoordIndices = getIntVector(subdata);
|
||||||
|
} else if (subdata.name == "Name") {
|
||||||
|
attrib.name = subdata.properties.at(0).toString().toStdString();
|
||||||
|
}
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
else {
|
||||||
|
int unknown = 0;
|
||||||
|
std::string subname = subdata.name.data();
|
||||||
|
if ( (subdata.name == "Version")
|
||||||
|
|| (subdata.name == "MappingInformationType")
|
||||||
|
|| (subdata.name == "ReferenceInformationType") ) {
|
||||||
|
} else {
|
||||||
|
unknown++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} else if (subdata.name == "UVIndex") {
|
QHash<QString, int>::iterator it = data.extracted.texcoordSetMap.find(QString(attrib.name.c_str()));
|
||||||
data.texCoordIndices = getIntVector(subdata);
|
if (it == data.extracted.texcoordSetMap.end()) {
|
||||||
|
data.extracted.texcoordSetMap.insert(QString(attrib.name.c_str()), data.attributes.size());
|
||||||
|
data.attributes.push_back(attrib);
|
||||||
|
} else {
|
||||||
|
// WTF same names for different UVs?
|
||||||
|
qDebug() << "LayerElementUV #" << attrib.index << " is reusing the same name as #" << (*it) << ". Skip this texcoord attribute.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (child.name == "LayerElementMaterial") {
|
} else if (child.name == "LayerElementMaterial") {
|
||||||
|
@ -1005,11 +1143,25 @@ public:
|
||||||
FBXTexture getTexture(const QString& textureID,
|
FBXTexture getTexture(const QString& textureID,
|
||||||
const QHash<QString, QString>& textureNames,
|
const QHash<QString, QString>& textureNames,
|
||||||
const QHash<QString, QByteArray>& textureFilenames,
|
const QHash<QString, QByteArray>& textureFilenames,
|
||||||
const QHash<QByteArray, QByteArray>& textureContent) {
|
const QHash<QByteArray, QByteArray>& textureContent,
|
||||||
|
const QHash<QString, TextureParam>& textureParams) {
|
||||||
FBXTexture texture;
|
FBXTexture texture;
|
||||||
texture.filename = textureFilenames.value(textureID);
|
texture.filename = textureFilenames.value(textureID);
|
||||||
texture.name = textureNames.value(textureID);
|
texture.name = textureNames.value(textureID);
|
||||||
texture.content = textureContent.value(texture.filename);
|
texture.content = textureContent.value(texture.filename);
|
||||||
|
texture.transform.setIdentity();
|
||||||
|
texture.texcoordSet = 0;
|
||||||
|
QHash<QString, TextureParam>::const_iterator it = textureParams.constFind(textureID);
|
||||||
|
if (it != textureParams.end()) {
|
||||||
|
const TextureParam& p = (*it);
|
||||||
|
texture.transform.setTranslation(p.translation);
|
||||||
|
texture.transform.setRotation(glm::quat(glm::radians(p.rotation)));
|
||||||
|
texture.transform.setScale(p.scaling);
|
||||||
|
if ((p.UVSet != "map1") || (p.UVSet != "UVSet0")) {
|
||||||
|
texture.texcoordSet = 1;
|
||||||
|
}
|
||||||
|
texture.texcoordSetName = p.UVSet;
|
||||||
|
}
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,6 +1177,23 @@ bool checkMaterialsHaveTextures(const QHash<QString, Material>& materials,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int matchTextureUVSetToAttributeChannel(const std::string& texUVSetName, const QHash<QString, int>& texcoordChannels) {
|
||||||
|
if (texUVSetName.empty()) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
QHash<QString, int>::const_iterator tcUnit = texcoordChannels.find(QString(texUVSetName.c_str()));
|
||||||
|
if (tcUnit != texcoordChannels.end()) {
|
||||||
|
int channel = (*tcUnit);
|
||||||
|
if (channel >= 2) {
|
||||||
|
channel = 0;
|
||||||
|
}
|
||||||
|
return channel;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) {
|
FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) {
|
||||||
QHash<QString, ExtractedMesh> meshes;
|
QHash<QString, ExtractedMesh> meshes;
|
||||||
QHash<QString, QString> modelIDsToNames;
|
QHash<QString, QString> modelIDsToNames;
|
||||||
|
@ -1039,12 +1208,14 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
QHash<QString, AnimationCurve> animationCurves;
|
QHash<QString, AnimationCurve> animationCurves;
|
||||||
QHash<QString, QString> textureNames;
|
QHash<QString, QString> textureNames;
|
||||||
QHash<QString, QByteArray> textureFilenames;
|
QHash<QString, QByteArray> textureFilenames;
|
||||||
|
QHash<QString, TextureParam> textureParams;
|
||||||
QHash<QByteArray, QByteArray> textureContent;
|
QHash<QByteArray, QByteArray> textureContent;
|
||||||
QHash<QString, Material> materials;
|
QHash<QString, Material> materials;
|
||||||
QHash<QString, QString> typeFlags;
|
QHash<QString, QString> typeFlags;
|
||||||
QHash<QString, QString> diffuseTextures;
|
QHash<QString, QString> diffuseTextures;
|
||||||
QHash<QString, QString> bumpTextures;
|
QHash<QString, QString> bumpTextures;
|
||||||
QHash<QString, QString> specularTextures;
|
QHash<QString, QString> specularTextures;
|
||||||
|
QHash<QString, QString> emissiveTextures;
|
||||||
QHash<QString, QString> localRotations;
|
QHash<QString, QString> localRotations;
|
||||||
QHash<QString, QString> xComponents;
|
QHash<QString, QString> xComponents;
|
||||||
QHash<QString, QString> yComponents;
|
QHash<QString, QString> yComponents;
|
||||||
|
@ -1099,7 +1270,9 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QMultiHash<QString, WeightedIndex> blendshapeChannelIndices;
|
QMultiHash<QString, WeightedIndex> blendshapeChannelIndices;
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
int unknown = 0;
|
||||||
|
#endif
|
||||||
FBXGeometry geometry;
|
FBXGeometry geometry;
|
||||||
float unitScaleFactor = 1.0f;
|
float unitScaleFactor = 1.0f;
|
||||||
foreach (const FBXNode& child, node.children) {
|
foreach (const FBXNode& child, node.children) {
|
||||||
|
@ -1302,6 +1475,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
models.insert(getID(object.properties), model);
|
models.insert(getID(object.properties), model);
|
||||||
|
|
||||||
} else if (object.name == "Texture") {
|
} else if (object.name == "Texture") {
|
||||||
|
TextureParam tex;
|
||||||
|
bool texparam = false;
|
||||||
foreach (const FBXNode& subobject, object.children) {
|
foreach (const FBXNode& subobject, object.children) {
|
||||||
if (subobject.name == "RelativeFilename") {
|
if (subobject.name == "RelativeFilename") {
|
||||||
// trim off any path information
|
// trim off any path information
|
||||||
|
@ -1313,7 +1488,65 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
QString name = QString(subobject.properties.at(0).toByteArray());
|
QString name = QString(subobject.properties.at(0).toByteArray());
|
||||||
name = name.left(name.indexOf('['));
|
name = name.left(name.indexOf('['));
|
||||||
textureNames.insert(getID(object.properties), name);
|
textureNames.insert(getID(object.properties), name);
|
||||||
|
} else if (subobject.name == "Texture_Alpha_Source") {
|
||||||
|
tex.assign<uint8_t>(tex.alphaSource, subobject.properties.at(0).value<int>());
|
||||||
|
} else if (subobject.name == "ModelUVTranslation") {
|
||||||
|
tex.assign(tex.UVTranslation, glm::vec2(subobject.properties.at(0).value<double>(),
|
||||||
|
subobject.properties.at(1).value<double>()));
|
||||||
|
} else if (subobject.name == "ModelUVScaling") {
|
||||||
|
tex.assign(tex.UVScaling, glm::vec2(subobject.properties.at(0).value<double>(),
|
||||||
|
subobject.properties.at(1).value<double>()));
|
||||||
|
} else if (subobject.name == "Cropping") {
|
||||||
|
tex.assign(tex.cropping, glm::vec4(subobject.properties.at(0).value<int>(),
|
||||||
|
subobject.properties.at(1).value<int>(),
|
||||||
|
subobject.properties.at(2).value<int>(),
|
||||||
|
subobject.properties.at(3).value<int>()));
|
||||||
|
} else if (subobject.name == "Properties70") {
|
||||||
|
QByteArray propertyName;
|
||||||
|
int index;
|
||||||
|
propertyName = "P";
|
||||||
|
index = 4;
|
||||||
|
foreach (const FBXNode& property, subobject.children) {
|
||||||
|
if (property.name == propertyName) {
|
||||||
|
QString v = property.properties.at(0).toString();
|
||||||
|
if (property.properties.at(0) == "UVSet") {
|
||||||
|
tex.assign(tex.UVSet, property.properties.at(index).toString().toStdString());
|
||||||
|
} else if (property.properties.at(0) == "CurrentTextureBlendMode") {
|
||||||
|
tex.assign<uint8_t>(tex.currentTextureBlendMode, property.properties.at(index).value<int>());
|
||||||
|
} else if (property.properties.at(0) == "UseMaterial") {
|
||||||
|
tex.assign<bool>(tex.useMaterial, property.properties.at(index).value<int>());
|
||||||
|
} else if (property.properties.at(0) == "Translation") {
|
||||||
|
tex.assign(tex.translation, getVec3(property.properties, index));
|
||||||
|
} else if (property.properties.at(0) == "Rotation") {
|
||||||
|
tex.assign(tex.rotation, getVec3(property.properties, index));
|
||||||
|
} else if (property.properties.at(0) == "Scaling") {
|
||||||
|
tex.assign(tex.scaling, getVec3(property.properties, index));
|
||||||
|
}
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
else {
|
||||||
|
std::string propName = v.toStdString();
|
||||||
|
unknown++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#if defined(DEBUG_FBXREADER)
|
||||||
|
else {
|
||||||
|
if (subobject.name == "Type") {
|
||||||
|
} else if (subobject.name == "Version") {
|
||||||
|
} else if (subobject.name == "FileName") {
|
||||||
|
} else if (subobject.name == "Media") {
|
||||||
|
} else {
|
||||||
|
std::string subname = subobject.name.data();
|
||||||
|
unknown++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tex.isDefault) {
|
||||||
|
textureParams.insert(getID(object.properties), tex);
|
||||||
}
|
}
|
||||||
} else if (object.name == "Video") {
|
} else if (object.name == "Video") {
|
||||||
QByteArray filename;
|
QByteArray filename;
|
||||||
|
@ -1425,6 +1658,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
ooChildToParent.insert(childID, parentID);
|
ooChildToParent.insert(childID, parentID);
|
||||||
}
|
}
|
||||||
if (connection.properties.at(0) == "OP") {
|
if (connection.properties.at(0) == "OP") {
|
||||||
|
int counter = 0;
|
||||||
QByteArray type = connection.properties.at(3).toByteArray().toLower();
|
QByteArray type = connection.properties.at(3).toByteArray().toLower();
|
||||||
if (type.contains("diffuse")) {
|
if (type.contains("diffuse")) {
|
||||||
diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
|
diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
|
||||||
|
@ -1446,6 +1680,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
|
|
||||||
} else if (type == "d|z") {
|
} else if (type == "d|z") {
|
||||||
zComponents.insert(getID(connection.properties, 2), getID(connection.properties, 1));
|
zComponents.insert(getID(connection.properties, 2), getID(connection.properties, 1));
|
||||||
|
|
||||||
|
} else if (type.contains("shininess")) {
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
} else if (type.contains("emissive")) {
|
||||||
|
emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parentMap.insert(getID(connection.properties, 1), getID(connection.properties, 2));
|
parentMap.insert(getID(connection.properties, 1), getID(connection.properties, 2));
|
||||||
|
@ -1650,33 +1893,63 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
const QString& childID = children.at(i);
|
const QString& childID = children.at(i);
|
||||||
if (materials.contains(childID)) {
|
if (materials.contains(childID)) {
|
||||||
Material material = materials.value(childID);
|
Material material = materials.value(childID);
|
||||||
|
bool detectDifferentUVs = false;
|
||||||
FBXTexture diffuseTexture;
|
FBXTexture diffuseTexture;
|
||||||
QString diffuseTextureID = diffuseTextures.value(childID);
|
QString diffuseTextureID = diffuseTextures.value(childID);
|
||||||
if (!diffuseTextureID.isNull()) {
|
if (!diffuseTextureID.isNull()) {
|
||||||
diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent);
|
diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent, textureParams);
|
||||||
|
|
||||||
// FBX files generated by 3DSMax have an intermediate texture parent, apparently
|
// FBX files generated by 3DSMax have an intermediate texture parent, apparently
|
||||||
foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) {
|
foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) {
|
||||||
if (textureFilenames.contains(childTextureID)) {
|
if (textureFilenames.contains(childTextureID)) {
|
||||||
diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent);
|
diffuseTexture = getTexture(diffuseTextureID, textureNames, textureFilenames, textureContent, textureParams);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
diffuseTexture.texcoordSet = matchTextureUVSetToAttributeChannel(diffuseTexture.texcoordSetName, extracted.texcoordSetMap);
|
||||||
|
|
||||||
|
detectDifferentUVs = (diffuseTexture.texcoordSet != 0) || (!diffuseTexture.transform.isIdentity());
|
||||||
}
|
}
|
||||||
|
|
||||||
FBXTexture normalTexture;
|
FBXTexture normalTexture;
|
||||||
QString bumpTextureID = bumpTextures.value(childID);
|
QString bumpTextureID = bumpTextures.value(childID);
|
||||||
if (!bumpTextureID.isNull()) {
|
if (!bumpTextureID.isNull()) {
|
||||||
normalTexture = getTexture(bumpTextureID, textureNames, textureFilenames, textureContent);
|
normalTexture = getTexture(bumpTextureID, textureNames, textureFilenames, textureContent, textureParams);
|
||||||
generateTangents = true;
|
generateTangents = true;
|
||||||
|
|
||||||
|
normalTexture.texcoordSet = matchTextureUVSetToAttributeChannel(normalTexture.texcoordSetName, extracted.texcoordSetMap);
|
||||||
|
|
||||||
|
detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity());
|
||||||
}
|
}
|
||||||
|
|
||||||
FBXTexture specularTexture;
|
FBXTexture specularTexture;
|
||||||
QString specularTextureID = specularTextures.value(childID);
|
QString specularTextureID = specularTextures.value(childID);
|
||||||
if (!specularTextureID.isNull()) {
|
if (!specularTextureID.isNull()) {
|
||||||
specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent);
|
specularTexture = getTexture(specularTextureID, textureNames, textureFilenames, textureContent, textureParams);
|
||||||
|
specularTexture.texcoordSet = matchTextureUVSetToAttributeChannel(specularTexture.texcoordSetName, extracted.texcoordSetMap);
|
||||||
|
detectDifferentUVs |= (specularTexture.texcoordSet != 0) || (!specularTexture.transform.isIdentity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FBXTexture emissiveTexture;
|
||||||
|
QString emissiveTextureID = emissiveTextures.value(childID);
|
||||||
|
if (!emissiveTextureID.isNull()) {
|
||||||
|
emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams);
|
||||||
|
|
||||||
|
// FBX files generated by 3DSMax have an intermediate texture parent, apparently
|
||||||
|
foreach (const QString& childTextureID, childMap.values(diffuseTextureID)) {
|
||||||
|
if (textureFilenames.contains(childTextureID)) {
|
||||||
|
emissiveTexture = getTexture(emissiveTextureID, textureNames, textureFilenames, textureContent, textureParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emissiveTexture.texcoordSet = matchTextureUVSetToAttributeChannel(emissiveTexture.texcoordSetName, extracted.texcoordSetMap);
|
||||||
|
|
||||||
|
detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detectDifferentUVs) {
|
||||||
|
detectDifferentUVs = false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
|
for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
|
||||||
if (extracted.partMaterialTextures.at(j).first == materialIndex) {
|
if (extracted.partMaterialTextures.at(j).first == materialIndex) {
|
||||||
FBXMeshPart& part = extracted.mesh.parts[j];
|
FBXMeshPart& part = extracted.mesh.parts[j];
|
||||||
|
@ -1694,13 +1967,16 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
||||||
if (!specularTexture.filename.isNull()) {
|
if (!specularTexture.filename.isNull()) {
|
||||||
part.specularTexture = specularTexture;
|
part.specularTexture = specularTexture;
|
||||||
}
|
}
|
||||||
|
if (!emissiveTexture.filename.isNull()) {
|
||||||
|
part.emissiveTexture = emissiveTexture;
|
||||||
|
}
|
||||||
part.materialID = material.id;
|
part.materialID = material.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
materialIndex++;
|
materialIndex++;
|
||||||
|
|
||||||
} else if (textureFilenames.contains(childID)) {
|
} else if (textureFilenames.contains(childID)) {
|
||||||
FBXTexture texture = getTexture(childID, textureNames, textureFilenames, textureContent);
|
FBXTexture texture = getTexture(childID, textureNames, textureFilenames, textureContent, textureParams);
|
||||||
for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
|
for (int j = 0; j < extracted.partMaterialTextures.size(); j++) {
|
||||||
int partTexture = extracted.partMaterialTextures.at(j).second;
|
int partTexture = extracted.partMaterialTextures.at(j).second;
|
||||||
if (partTexture == textureIndex && !(partTexture == 0 && materialsHaveTextures)) {
|
if (partTexture == textureIndex && !(partTexture == 0 && materialsHaveTextures)) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include <Extents.h>
|
#include <Extents.h>
|
||||||
|
#include <Transform.h>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
@ -102,6 +103,10 @@ public:
|
||||||
QString name;
|
QString name;
|
||||||
QByteArray filename;
|
QByteArray filename;
|
||||||
QByteArray content;
|
QByteArray content;
|
||||||
|
|
||||||
|
Transform transform;
|
||||||
|
int texcoordSet;
|
||||||
|
std::string texcoordSetName;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A single part of a mesh (with the same material).
|
/// A single part of a mesh (with the same material).
|
||||||
|
@ -120,6 +125,7 @@ public:
|
||||||
FBXTexture diffuseTexture;
|
FBXTexture diffuseTexture;
|
||||||
FBXTexture normalTexture;
|
FBXTexture normalTexture;
|
||||||
FBXTexture specularTexture;
|
FBXTexture specularTexture;
|
||||||
|
FBXTexture emissiveTexture;
|
||||||
|
|
||||||
QString materialID;
|
QString materialID;
|
||||||
};
|
};
|
||||||
|
@ -135,18 +141,20 @@ public:
|
||||||
QVector<glm::vec3> tangents;
|
QVector<glm::vec3> tangents;
|
||||||
QVector<glm::vec3> colors;
|
QVector<glm::vec3> colors;
|
||||||
QVector<glm::vec2> texCoords;
|
QVector<glm::vec2> texCoords;
|
||||||
|
QVector<glm::vec2> texCoords1;
|
||||||
QVector<glm::vec4> clusterIndices;
|
QVector<glm::vec4> clusterIndices;
|
||||||
QVector<glm::vec4> clusterWeights;
|
QVector<glm::vec4> clusterWeights;
|
||||||
|
|
||||||
QVector<FBXCluster> clusters;
|
QVector<FBXCluster> clusters;
|
||||||
|
|
||||||
Extents meshExtents;
|
Extents meshExtents;
|
||||||
|
|
||||||
bool isEye;
|
bool isEye;
|
||||||
|
|
||||||
QVector<FBXBlendshape> blendshapes;
|
QVector<FBXBlendshape> blendshapes;
|
||||||
|
|
||||||
bool hasSpecularTexture() const;
|
bool hasSpecularTexture() const;
|
||||||
|
bool hasEmissiveTexture() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A single animation frame extracted from an FBX document.
|
/// A single animation frame extracted from an FBX document.
|
||||||
|
|
|
@ -136,7 +136,10 @@ protected:
|
||||||
void invalidCache() const { _flags.set(FLAG_CACHE_INVALID, true); }
|
void invalidCache() const { _flags.set(FLAG_CACHE_INVALID, true); }
|
||||||
|
|
||||||
void flagTranslation() { _flags.set(FLAG_TRANSLATION, true); }
|
void flagTranslation() { _flags.set(FLAG_TRANSLATION, true); }
|
||||||
|
void unflagTranslation() { _flags.set(FLAG_TRANSLATION, false); }
|
||||||
|
|
||||||
void flagRotation() { _flags.set(FLAG_ROTATION, true); }
|
void flagRotation() { _flags.set(FLAG_ROTATION, true); }
|
||||||
|
void unflagRotation() { _flags.set(FLAG_ROTATION, false); }
|
||||||
|
|
||||||
void flagScaling() { _flags.set(FLAG_SCALING, true); }
|
void flagScaling() { _flags.set(FLAG_SCALING, true); }
|
||||||
void unflagScaling() { _flags.set(FLAG_SCALING, false); }
|
void unflagScaling() { _flags.set(FLAG_SCALING, false); }
|
||||||
|
@ -162,17 +165,23 @@ inline const Transform::Vec3& Transform::getTranslation() const {
|
||||||
|
|
||||||
inline void Transform::setTranslation(const Vec3& translation) {
|
inline void Transform::setTranslation(const Vec3& translation) {
|
||||||
invalidCache();
|
invalidCache();
|
||||||
flagTranslation();
|
if (translation == Vec3()) {
|
||||||
|
unflagTranslation();
|
||||||
|
} else {
|
||||||
|
flagTranslation();
|
||||||
|
}
|
||||||
_translation = translation;
|
_translation = translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Transform::preTranslate(const Vec3& translation) {
|
inline void Transform::preTranslate(const Vec3& translation) {
|
||||||
|
if (translation == Vec3() ) return;
|
||||||
invalidCache();
|
invalidCache();
|
||||||
flagTranslation();
|
flagTranslation();
|
||||||
_translation += translation;
|
_translation += translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Transform::postTranslate(const Vec3& translation) {
|
inline void Transform::postTranslate(const Vec3& translation) {
|
||||||
|
if (translation == Vec3() ) return;
|
||||||
invalidCache();
|
invalidCache();
|
||||||
flagTranslation();
|
flagTranslation();
|
||||||
|
|
||||||
|
@ -192,11 +201,16 @@ inline const Transform::Quat& Transform::getRotation() const {
|
||||||
|
|
||||||
inline void Transform::setRotation(const Quat& rotation) {
|
inline void Transform::setRotation(const Quat& rotation) {
|
||||||
invalidCache();
|
invalidCache();
|
||||||
flagRotation();
|
if (rotation == Quat()) {
|
||||||
|
unflagRotation();
|
||||||
|
} else {
|
||||||
|
flagRotation();
|
||||||
|
}
|
||||||
_rotation = rotation;
|
_rotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Transform::preRotate(const Quat& rotation) {
|
inline void Transform::preRotate(const Quat& rotation) {
|
||||||
|
if (rotation == Quat()) return;
|
||||||
invalidCache();
|
invalidCache();
|
||||||
if (isRotating()) {
|
if (isRotating()) {
|
||||||
_rotation = rotation * _rotation;
|
_rotation = rotation * _rotation;
|
||||||
|
@ -204,10 +218,12 @@ inline void Transform::preRotate(const Quat& rotation) {
|
||||||
_rotation = rotation;
|
_rotation = rotation;
|
||||||
}
|
}
|
||||||
flagRotation();
|
flagRotation();
|
||||||
|
|
||||||
_translation = glm::rotate(rotation, _translation);
|
_translation = glm::rotate(rotation, _translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Transform::postRotate(const Quat& rotation) {
|
inline void Transform::postRotate(const Quat& rotation) {
|
||||||
|
if (rotation == Quat()) return;
|
||||||
invalidCache();
|
invalidCache();
|
||||||
|
|
||||||
if (isNonUniform()) {
|
if (isNonUniform()) {
|
||||||
|
|
Loading…
Reference in a new issue