parent
429c92ad75
commit
f40fbdf4ad
|
|
@ -328,14 +328,16 @@ public:
|
|||
// bit 0 = alpha mode blend (1) or opaque (0)
|
||||
// bit 1 = rigged (1) or static (0)
|
||||
// bit 2 = unlit (1) or lit (0)
|
||||
// bit 3 = single (0) or multi (1) uv coordinates
|
||||
struct GLTFVariant
|
||||
{
|
||||
constexpr static U8 ALPHA_BLEND = 1;
|
||||
constexpr static U8 RIGGED = 2;
|
||||
constexpr static U8 UNLIT = 4;
|
||||
constexpr static U8 MULTI_UV = 8;
|
||||
};
|
||||
|
||||
constexpr static U8 NUM_GLTF_VARIANTS = 8;
|
||||
constexpr static U8 NUM_GLTF_VARIANTS = 16;
|
||||
|
||||
std::vector<LLGLSLShader> mGLTFVariants;
|
||||
|
||||
|
|
|
|||
|
|
@ -1686,7 +1686,7 @@ void LLRender::flush()
|
|||
|
||||
if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0)
|
||||
{
|
||||
vb->setTexCoordData(mTexcoordsp.get());
|
||||
vb->setTexCoord0Data(mTexcoordsp.get());
|
||||
}
|
||||
|
||||
if (attribute_mask & LLVertexBuffer::MAP_COLOR)
|
||||
|
|
|
|||
|
|
@ -1180,6 +1180,11 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("texture_metallic_roughness_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("texture_occlusion_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("texture_emissive_transform"); // (GLTF)
|
||||
mReservedUniforms.push_back("base_color_texcoord"); // (GLTF)
|
||||
mReservedUniforms.push_back("emissive_texcoord"); // (GLTF)
|
||||
mReservedUniforms.push_back("normal_texcoord"); // (GLTF)
|
||||
mReservedUniforms.push_back("metallic_roughness_texcoord"); // (GLTF)
|
||||
mReservedUniforms.push_back("occlusion_texcoord"); // (GLTF)
|
||||
|
||||
mReservedUniforms.push_back("terrain_texture_transforms"); // (GLTF)
|
||||
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ public:
|
|||
TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, // "texture_metallic_roughness_transform" (GLTF)
|
||||
TEXTURE_OCCLUSION_TRANSFORM, // "texture_occlusion_transform" (GLTF)
|
||||
TEXTURE_EMISSIVE_TRANSFORM, // "texture_emissive_transform" (GLTF)
|
||||
BASE_COLOR_TEXCOORD, // "base_color_texcoord" (GLTF)
|
||||
EMISSIVE_TEXCOORD, // "emissive_texcoord" (GLTF)
|
||||
NORMAL_TEXCOORD, // "normal_texcoord" (GLTF)
|
||||
METALLIC_ROUGHNESS_TEXCOORD, // "metallic_roughness_texcoord" (GLTF)
|
||||
OCCLUSION_TEXCOORD, // "occlusion_texcoord" (GLTF)
|
||||
|
||||
TERRAIN_TEXTURE_TRANSFORMS, // "terrain_texture_transforms" (GLTF)
|
||||
|
||||
|
|
|
|||
|
|
@ -1635,7 +1635,7 @@ void LLVertexBuffer::setPositionData(const LLVector4a* data)
|
|||
flush_vbo(GL_ARRAY_BUFFER, 0, sizeof(LLVector4a) * getNumVerts()-1, (U8*) data, mMappedData);
|
||||
}
|
||||
|
||||
void LLVertexBuffer::setTexCoordData(const LLVector2* data)
|
||||
void LLVertexBuffer::setTexCoord0Data(const LLVector2* data)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
llassert(sGLRenderBuffer == mGLBuffer);
|
||||
|
|
@ -1643,6 +1643,14 @@ void LLVertexBuffer::setTexCoordData(const LLVector2* data)
|
|||
flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD0], mOffsets[TYPE_TEXCOORD0] + sTypeSize[TYPE_TEXCOORD0] * getNumVerts() - 1, (U8*)data, mMappedData);
|
||||
}
|
||||
|
||||
void LLVertexBuffer::setTexCoord1Data(const LLVector2* data)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
llassert(sGLRenderBuffer == mGLBuffer);
|
||||
#endif
|
||||
flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TEXCOORD1], mOffsets[TYPE_TEXCOORD1] + sTypeSize[TYPE_TEXCOORD1] * getNumVerts() - 1, (U8*)data, mMappedData);
|
||||
}
|
||||
|
||||
void LLVertexBuffer::setColorData(const LLColor4U* data)
|
||||
{
|
||||
#if !LL_DARWIN
|
||||
|
|
|
|||
|
|
@ -196,7 +196,8 @@ public:
|
|||
void setTangentData(const LLVector4a* data);
|
||||
void setWeight4Data(const LLVector4a* data);
|
||||
void setJointData(const U64* data);
|
||||
void setTexCoordData(const LLVector2* data);
|
||||
void setTexCoord0Data(const LLVector2* data);
|
||||
void setTexCoord1Data(const LLVector2* data);
|
||||
void setColorData(const LLColor4U* data);
|
||||
void setIndexData(const U16* data);
|
||||
void setIndexData(const U32* data);
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ uniform sampler2D emissiveMap;
|
|||
uniform vec3 emissiveColor;
|
||||
in vec3 vary_position;
|
||||
in vec4 vertex_color;
|
||||
in vec2 base_color_texcoord;
|
||||
in vec2 emissive_texcoord;
|
||||
in vec2 base_color_uv;
|
||||
in vec2 emissive_uv;
|
||||
uniform float minimum_alpha;
|
||||
|
||||
void mirrorClip(vec3 pos);
|
||||
|
|
@ -59,9 +59,9 @@ uniform float roughnessFactor;
|
|||
in vec3 vary_normal;
|
||||
in vec3 vary_tangent;
|
||||
flat in float vary_sign;
|
||||
in vec2 normal_texcoord;
|
||||
in vec2 metallic_roughness_texcoord;
|
||||
in vec2 occlusion_texcoord;
|
||||
in vec2 normal_uv;
|
||||
in vec2 metallic_roughness_uv;
|
||||
in vec2 occlusion_uv;
|
||||
#endif
|
||||
// ==================================
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ void main()
|
|||
vec3 pos = vary_position;
|
||||
mirrorClip(pos);
|
||||
|
||||
vec4 basecolor = texture(diffuseMap, base_color_texcoord.xy).rgba;
|
||||
vec4 basecolor = texture(diffuseMap, base_color_uv.xy).rgba;
|
||||
basecolor.rgb = srgb_to_linear(basecolor.rgb);
|
||||
basecolor *= vertex_color;
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ void main()
|
|||
}
|
||||
|
||||
vec3 emissive = emissiveColor;
|
||||
emissive *= srgb_to_linear(texture(emissiveMap, emissive_texcoord.xy).rgb);
|
||||
emissive *= srgb_to_linear(texture(emissiveMap, emissive_uv.xy).rgb);
|
||||
// ==================================
|
||||
|
||||
// ==================================
|
||||
|
|
@ -185,7 +185,7 @@ void main()
|
|||
// ==================================
|
||||
#ifndef UNLIT
|
||||
// from mikktspace.com
|
||||
vec3 vNt = texture(normalMap, normal_texcoord.xy).xyz*2.0-1.0;
|
||||
vec3 vNt = texture(normalMap, normal_uv.xy).xyz*2.0-1.0;
|
||||
float sign = vary_sign;
|
||||
vec3 vN = vary_normal;
|
||||
vec3 vT = vary_tangent.xyz;
|
||||
|
|
@ -199,8 +199,8 @@ void main()
|
|||
// occlusion 1.0
|
||||
// roughness 0.0
|
||||
// metal 0.0
|
||||
vec3 orm = texture(metallicRoughnessMap, metallic_roughness_texcoord.xy).rgb;
|
||||
orm.r = texture(occlusionMap, occlusion_texcoord.xy).r;
|
||||
vec3 orm = texture(metallicRoughnessMap, metallic_roughness_uv.xy).rgb;
|
||||
orm.r = texture(occlusionMap, occlusion_uv.xy).r;
|
||||
orm.g *= roughnessFactor;
|
||||
orm.b *= metallicFactor;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ uniform mat4 projection_matrix;
|
|||
uniform mat3 normal_matrix;
|
||||
uniform mat4 modelview_projection_matrix;
|
||||
#endif
|
||||
uniform mat4 texture_matrix0;
|
||||
|
||||
uniform vec4[2] texture_base_color_transform;
|
||||
uniform vec4[2] texture_normal_transform;
|
||||
|
|
@ -44,21 +43,31 @@ uniform vec4[2] texture_occlusion_transform;
|
|||
in vec3 position;
|
||||
in vec4 diffuse_color;
|
||||
in vec2 texcoord0;
|
||||
out vec2 base_color_texcoord;
|
||||
out vec2 emissive_texcoord;
|
||||
out vec2 base_color_uv;
|
||||
out vec2 emissive_uv;
|
||||
out vec4 vertex_color;
|
||||
out vec3 vary_position;
|
||||
|
||||
#ifndef UNLIT
|
||||
in vec3 normal;
|
||||
in vec4 tangent;
|
||||
out vec2 normal_texcoord;
|
||||
out vec2 metallic_roughness_texcoord;
|
||||
out vec2 occlusion_texcoord;
|
||||
out vec2 normal_uv;
|
||||
out vec2 metallic_roughness_uv;
|
||||
out vec2 occlusion_uv;
|
||||
out vec3 vary_tangent;
|
||||
flat out float vary_sign;
|
||||
out vec3 vary_normal;
|
||||
vec3 tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform, mat4 sl_animation_transform);
|
||||
#endif
|
||||
|
||||
#ifdef MULTI_UV
|
||||
in vec2 texcoord1;
|
||||
uniform int base_color_texcoord;
|
||||
uniform int emissive_texcoord;
|
||||
#ifndef UNLIT
|
||||
uniform int normal_texcoord;
|
||||
uniform int metallic_roughness_texcoord;
|
||||
uniform int occlusion_texcoord;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
vec2 gltf_texture_transform(vec2 texcoord, vec4[2] p)
|
||||
|
|
@ -86,6 +95,36 @@ vec2 gltf_texture_transform(vec2 texcoord, vec4[2] p)
|
|||
return uvTransformed;
|
||||
}
|
||||
|
||||
#ifndef UNLIT
|
||||
vec3 gltf_tangent_space_transform(vec4 vertex_tangent, vec3 vertex_normal, vec4[2] khr_gltf_transform)
|
||||
{ //derived from tangent_space_transform in textureUtilV.glsl
|
||||
vec2 weights = vec2(0, 1);
|
||||
|
||||
// Convert to left-handed coordinate system
|
||||
weights.y = -weights.y;
|
||||
|
||||
// Apply KHR_texture_transform (rotation only)
|
||||
float khr_rotation = khr_gltf_transform[0].z;
|
||||
mat2 khr_rotation_mat = mat2(
|
||||
cos(khr_rotation),-sin(khr_rotation),
|
||||
sin(khr_rotation), cos(khr_rotation)
|
||||
);
|
||||
weights = khr_rotation_mat * weights;
|
||||
|
||||
// Convert back to right-handed coordinate system
|
||||
weights.y = -weights.y;
|
||||
|
||||
// Similar to the MikkTSpace-compatible method of extracting the binormal
|
||||
// from the normal and tangent, as seen in the fragment shader
|
||||
vec3 vertex_binormal = vertex_tangent.w * cross(vertex_normal, vertex_tangent.xyz);
|
||||
|
||||
return (weights.x * vertex_binormal.xyz) + (weights.y * vertex_tangent.xyz);
|
||||
|
||||
return vertex_tangent.xyz;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef ALPHA_BLEND
|
||||
out vec3 vary_fragcoord;
|
||||
|
|
@ -161,13 +200,40 @@ void main()
|
|||
gl_Position = vert;
|
||||
#endif
|
||||
|
||||
base_color_texcoord = gltf_texture_transform(texcoord0, texture_base_color_transform);
|
||||
emissive_texcoord = gltf_texture_transform(texcoord0, texture_emissive_transform);
|
||||
vec2 bcuv;
|
||||
vec2 emuv;
|
||||
|
||||
#ifdef MULTI_UV
|
||||
vec2 uv[2];
|
||||
uv[0] = texcoord0;
|
||||
uv[1] = texcoord1;
|
||||
|
||||
bcuv = uv[base_color_texcoord];
|
||||
emuv = uv[emissive_texcoord];
|
||||
#else
|
||||
bcuv = texcoord0;
|
||||
emuv = texcoord0;
|
||||
#endif
|
||||
|
||||
base_color_uv = gltf_texture_transform(bcuv, texture_base_color_transform);
|
||||
emissive_uv = gltf_texture_transform(emuv, texture_emissive_transform);
|
||||
|
||||
#ifndef UNLIT
|
||||
normal_texcoord = gltf_texture_transform(texcoord0, texture_normal_transform);
|
||||
metallic_roughness_texcoord = gltf_texture_transform(texcoord0, texture_metallic_roughness_transform);
|
||||
occlusion_texcoord = gltf_texture_transform(texcoord0, texture_occlusion_transform);
|
||||
vec2 normuv;
|
||||
vec2 rmuv;
|
||||
vec2 ouv;
|
||||
#ifdef MULTI_UV
|
||||
normuv = uv[normal_texcoord];
|
||||
rmuv = uv[metallic_roughness_texcoord];
|
||||
ouv = uv[occlusion_texcoord];
|
||||
#else
|
||||
normuv = texcoord0;
|
||||
rmuv = texcoord0;
|
||||
ouv = texcoord0;
|
||||
#endif
|
||||
normal_uv = gltf_texture_transform(normuv, texture_normal_transform);
|
||||
metallic_roughness_uv = gltf_texture_transform(rmuv, texture_metallic_roughness_transform);
|
||||
occlusion_uv = gltf_texture_transform(ouv, texture_occlusion_transform);
|
||||
#endif
|
||||
|
||||
#ifndef UNLIT
|
||||
|
|
@ -180,7 +246,7 @@ void main()
|
|||
#endif
|
||||
|
||||
n = normalize(n);
|
||||
vary_tangent = normalize(tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform, texture_matrix0));
|
||||
vary_tangent = normalize(gltf_tangent_space_transform(vec4(t, tangent.w), n, texture_normal_transform));
|
||||
vary_sign = tangent.w;
|
||||
vary_normal = n;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -910,6 +910,24 @@ void Material::TextureInfo::serialize(object& dst) const
|
|||
write_extensions(dst, &mTextureTransform, "KHR_texture_transform");
|
||||
}
|
||||
|
||||
S32 Material::TextureInfo::getTexCoord() const
|
||||
{
|
||||
if (mTextureTransform.mPresent && mTextureTransform.mTexCoord != INVALID_INDEX)
|
||||
{
|
||||
return mTextureTransform.mTexCoord;
|
||||
}
|
||||
return mTexCoord;
|
||||
}
|
||||
|
||||
bool Material::isMultiUV() const
|
||||
{
|
||||
return mPbrMetallicRoughness.mBaseColorTexture.getTexCoord() != 0 ||
|
||||
mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord() != 0 ||
|
||||
mNormalTexture.getTexCoord() != 0 ||
|
||||
mOcclusionTexture.getTexCoord() != 0 ||
|
||||
mEmissiveTexture.getTexCoord() != 0;
|
||||
}
|
||||
|
||||
const Material::TextureInfo& Material::TextureInfo::operator=(const Value& src)
|
||||
{
|
||||
if (src.is_object())
|
||||
|
|
@ -1048,7 +1066,7 @@ void TextureTransform::serialize(object& dst) const
|
|||
write(mOffset, "offset", dst, vec2(0.f, 0.f));
|
||||
write(mRotation, "rotation", dst, 0.f);
|
||||
write(mScale, "scale", dst, vec2(1.f, 1.f));
|
||||
write(mTexCoord, "texCoord", dst, 0);
|
||||
write(mTexCoord, "texCoord", dst, -1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -102,6 +102,10 @@ namespace LL
|
|||
bool operator==(const TextureInfo& rhs) const;
|
||||
bool operator!=(const TextureInfo& rhs) const;
|
||||
|
||||
// get the UV channel that should be used for sampling this texture
|
||||
// returns mTextureTransform.mTexCoord if present and valid, otherwise mTexCoord
|
||||
S32 getTexCoord() const;
|
||||
|
||||
const TextureInfo& operator=(const Value& src);
|
||||
void serialize(boost::json::object& dst) const;
|
||||
};
|
||||
|
|
@ -152,6 +156,8 @@ namespace LL
|
|||
bool mDoubleSided = false;
|
||||
Unlit mUnlit;
|
||||
|
||||
bool isMultiUV() const;
|
||||
|
||||
const Material& operator=(const Value& src);
|
||||
void serialize(boost::json::object& dst) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -826,7 +826,7 @@ namespace LL
|
|||
if (arr.size() == 2)
|
||||
{
|
||||
std::error_code ec;
|
||||
vec3 t;
|
||||
vec2 t;
|
||||
t.x = arr[0].to_number<F32>(ec); if (ec) return false;
|
||||
t.y = arr[1].to_number<F32>(ec); if (ec) return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,13 +42,14 @@ using namespace boost::json;
|
|||
// Mesh data useful for Mikktspace tangent generation (and flat normal generation)
|
||||
struct MikktMesh
|
||||
{
|
||||
std::vector<LLVector3> p;
|
||||
std::vector<LLVector3> n;
|
||||
std::vector<LLVector2> tc;
|
||||
std::vector<LLVector4> w;
|
||||
std::vector<LLVector4> t;
|
||||
std::vector<LLColor4U> c;
|
||||
std::vector<U64> j;
|
||||
std::vector<LLVector3> p; //positions
|
||||
std::vector<LLVector3> n; //normals
|
||||
std::vector<LLVector4> t; //tangents
|
||||
std::vector<LLVector2> tc0; //texcoords 0
|
||||
std::vector<LLVector2> tc1; //texcoords 1
|
||||
std::vector<LLColor4U> c; //colors
|
||||
std::vector<LLVector4> w; //weights
|
||||
std::vector<U64> j; //joints
|
||||
|
||||
// initialize from src primitive and make an unrolled triangle list
|
||||
// returns false if the Primitive cannot be converted to a triangle list
|
||||
|
|
@ -57,15 +58,28 @@ struct MikktMesh
|
|||
bool indexed = !prim->mIndexArray.empty();
|
||||
U32 vert_count = indexed ? prim->mIndexArray.size() : prim->mPositions.size();
|
||||
|
||||
if (prim->mMode != Primitive::Mode::TRIANGLES)
|
||||
U32 triangle_count = 0;
|
||||
|
||||
if (prim->mMode == Primitive::Mode::TRIANGLE_STRIP ||
|
||||
prim->mMode == Primitive::Mode::TRIANGLE_FAN)
|
||||
{
|
||||
LL_WARNS("GLTF") << "Unsupported primitive mode for conversion to triangles: " << (S32) prim->mMode << LL_ENDL;
|
||||
triangle_count = vert_count - 2;
|
||||
}
|
||||
else if (prim->mMode == Primitive::Mode::TRIANGLES)
|
||||
{
|
||||
triangle_count = vert_count / 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("GLTF") << "Unsupported primitive mode for conversion to triangles: " << (S32)prim->mMode << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
vert_count = triangle_count * 3;
|
||||
|
||||
p.resize(vert_count);
|
||||
n.resize(vert_count);
|
||||
tc.resize(vert_count);
|
||||
tc0.resize(vert_count);
|
||||
c.resize(vert_count);
|
||||
|
||||
bool has_normals = !prim->mNormals.empty();
|
||||
|
|
@ -78,6 +92,7 @@ struct MikktMesh
|
|||
{
|
||||
t.resize(vert_count);
|
||||
}
|
||||
|
||||
bool rigged = !prim->mWeights.empty();
|
||||
if (rigged)
|
||||
{
|
||||
|
|
@ -85,23 +100,69 @@ struct MikktMesh
|
|||
j.resize(vert_count);
|
||||
}
|
||||
|
||||
for (int i = 0; i < vert_count; ++i)
|
||||
bool multi_uv = !prim->mTexCoords1.empty();
|
||||
if (multi_uv)
|
||||
{
|
||||
U32 idx = indexed ? prim->mIndexArray[i] : i;
|
||||
tc1.resize(vert_count);
|
||||
}
|
||||
|
||||
p[i].set(prim->mPositions[idx].getF32ptr());
|
||||
tc[i].set(prim->mTexCoords[idx]);
|
||||
c[i] = prim->mColors[idx];
|
||||
for (int tri_idx = 0; tri_idx < triangle_count; ++tri_idx)
|
||||
{
|
||||
U32 idx[3];
|
||||
|
||||
if (has_normals)
|
||||
if (prim->mMode == Primitive::Mode::TRIANGLES)
|
||||
{
|
||||
n[i].set(prim->mNormals[idx].getF32ptr());
|
||||
idx[0] = tri_idx * 3;
|
||||
idx[1] = tri_idx * 3 + 1;
|
||||
idx[2] = tri_idx * 3 + 2;
|
||||
}
|
||||
else if (prim->mMode == Primitive::Mode::TRIANGLE_STRIP)
|
||||
{
|
||||
idx[0] = tri_idx;
|
||||
idx[1] = tri_idx + 1;
|
||||
idx[2] = tri_idx + 2;
|
||||
|
||||
if (tri_idx % 2 != 0)
|
||||
{
|
||||
std::swap(idx[1], idx[2]);
|
||||
}
|
||||
}
|
||||
else if (prim->mMode == Primitive::Mode::TRIANGLE_FAN)
|
||||
{
|
||||
idx[0] = 0;
|
||||
idx[1] = tri_idx + 1;
|
||||
idx[2] = tri_idx + 2;
|
||||
}
|
||||
|
||||
if (rigged)
|
||||
if (indexed)
|
||||
{
|
||||
w[i].set(prim->mWeights[idx].getF32ptr());
|
||||
j[i] = prim->mJoints[idx];
|
||||
idx[0] = prim->mIndexArray[idx[0]];
|
||||
idx[1] = prim->mIndexArray[idx[1]];
|
||||
idx[2] = prim->mIndexArray[idx[2]];
|
||||
}
|
||||
|
||||
for (U32 v = 0; v < 3; ++v)
|
||||
{
|
||||
U32 i = tri_idx * 3 + v;
|
||||
p[i].set(prim->mPositions[idx[v]].getF32ptr());
|
||||
tc0[i].set(prim->mTexCoords0[idx[v]]);
|
||||
c[i] = prim->mColors[idx[v]];
|
||||
|
||||
if (multi_uv)
|
||||
{
|
||||
tc1[i].set(prim->mTexCoords1[idx[v]]);
|
||||
}
|
||||
|
||||
if (has_normals)
|
||||
{
|
||||
n[i].set(prim->mNormals[idx[v]].getF32ptr());
|
||||
}
|
||||
|
||||
if (rigged)
|
||||
{
|
||||
w[i].set(prim->mWeights[idx[v]].getF32ptr());
|
||||
j[i] = prim->mJoints[idx[v]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -138,25 +199,34 @@ struct MikktMesh
|
|||
void write(Primitive* prim) const
|
||||
{
|
||||
//re-weld
|
||||
meshopt_Stream mos[] =
|
||||
std::vector<meshopt_Stream> mos =
|
||||
{
|
||||
{ &p[0], sizeof(LLVector3), sizeof(LLVector3) },
|
||||
{ &n[0], sizeof(LLVector3), sizeof(LLVector3) },
|
||||
{ &t[0], sizeof(LLVector4), sizeof(LLVector4) },
|
||||
{ &tc[0], sizeof(LLVector2), sizeof(LLVector2) },
|
||||
{ &c[0], sizeof(LLColor4U), sizeof(LLColor4U) },
|
||||
{ w.empty() ? nullptr : &w[0], sizeof(LLVector4), sizeof(LLVector4) },
|
||||
{ j.empty() ? nullptr : &j[0], sizeof(U64), sizeof(U64) }
|
||||
{ &tc0[0], sizeof(LLVector2), sizeof(LLVector2) },
|
||||
{ &c[0], sizeof(LLColor4U), sizeof(LLColor4U) }
|
||||
};
|
||||
|
||||
if (!w.empty())
|
||||
{
|
||||
mos.push_back({ &w[0], sizeof(LLVector4), sizeof(LLVector4) });
|
||||
mos.push_back({ &j[0], sizeof(U64), sizeof(U64) });
|
||||
}
|
||||
|
||||
if (!tc1.empty())
|
||||
{
|
||||
mos.push_back({ &tc1[0], sizeof(LLVector2), sizeof(LLVector2) });
|
||||
}
|
||||
|
||||
std::vector<U32> remap;
|
||||
remap.resize(p.size());
|
||||
|
||||
U32 stream_count = w.empty() ? 5 : 7;
|
||||
U32 stream_count = mos.size();
|
||||
|
||||
size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, p.size(), p.size(), mos, stream_count);
|
||||
size_t vert_count = meshopt_generateVertexRemapMulti(&remap[0], nullptr, p.size(), p.size(), mos.data(), stream_count);
|
||||
|
||||
prim->mTexCoords.resize(vert_count);
|
||||
prim->mTexCoords0.resize(vert_count);
|
||||
prim->mNormals.resize(vert_count);
|
||||
prim->mTangents.resize(vert_count);
|
||||
prim->mPositions.resize(vert_count);
|
||||
|
|
@ -166,6 +236,10 @@ struct MikktMesh
|
|||
prim->mWeights.resize(vert_count);
|
||||
prim->mJoints.resize(vert_count);
|
||||
}
|
||||
if (!tc1.empty())
|
||||
{
|
||||
prim->mTexCoords1.resize(vert_count);
|
||||
}
|
||||
|
||||
prim->mIndexArray.resize(remap.size());
|
||||
|
||||
|
|
@ -178,7 +252,7 @@ struct MikktMesh
|
|||
|
||||
prim->mPositions[dst_idx].load3(p[src_idx].mV);
|
||||
prim->mNormals[dst_idx].load3(n[src_idx].mV);
|
||||
prim->mTexCoords[dst_idx] = tc[src_idx];
|
||||
prim->mTexCoords0[dst_idx] = tc0[src_idx];
|
||||
prim->mTangents[dst_idx].loadua(t[src_idx].mV);
|
||||
prim->mColors[dst_idx] = c[src_idx];
|
||||
|
||||
|
|
@ -187,6 +261,11 @@ struct MikktMesh
|
|||
prim->mWeights[dst_idx].loadua(w[src_idx].mV);
|
||||
prim->mJoints[dst_idx] = j[src_idx];
|
||||
}
|
||||
|
||||
if (!tc1.empty())
|
||||
{
|
||||
prim->mTexCoords1[dst_idx] = tc1[src_idx];
|
||||
}
|
||||
}
|
||||
|
||||
prim->mGLMode = LLRender::TRIANGLES;
|
||||
|
|
@ -210,8 +289,8 @@ struct MikktMesh
|
|||
|
||||
mikk::float3 GetTexCoord(const uint32_t face_num, const uint32_t vert_num)
|
||||
{
|
||||
F32* uv = tc[face_num * 3 + vert_num].mV;
|
||||
return mikk::float3(uv[0], uv[1], 1.0f);
|
||||
F32* uv = tc0[face_num * 3 + vert_num].mV;
|
||||
return mikk::float3(uv[0], 1.f-uv[1], 1.0f);
|
||||
}
|
||||
|
||||
mikk::float3 GetNormal(const uint32_t face_num, const uint32_t vert_num)
|
||||
|
|
@ -228,6 +307,14 @@ struct MikktMesh
|
|||
};
|
||||
|
||||
|
||||
static void vertical_flip(std::vector<LLVector2>& texcoords)
|
||||
{
|
||||
for (auto& tc : texcoords)
|
||||
{
|
||||
tc[1] = 1.f - tc[1];
|
||||
}
|
||||
}
|
||||
|
||||
bool Primitive::prep(Asset& asset)
|
||||
{
|
||||
// allocate vertex buffer
|
||||
|
|
@ -261,7 +348,11 @@ bool Primitive::prep(Asset& asset)
|
|||
}
|
||||
else if (attribName == "TEXCOORD_0")
|
||||
{
|
||||
copy(asset, accessor, mTexCoords);
|
||||
copy(asset, accessor, mTexCoords0);
|
||||
}
|
||||
else if (attribName == "TEXCOORD_1")
|
||||
{
|
||||
copy(asset, accessor, mTexCoords1);
|
||||
}
|
||||
else if (attribName == "JOINTS_0")
|
||||
{
|
||||
|
|
@ -297,24 +388,28 @@ bool Primitive::prep(Asset& asset)
|
|||
mask |= LLVertexBuffer::MAP_JOINT;
|
||||
}
|
||||
|
||||
if (mTexCoords.empty())
|
||||
if (mTexCoords0.empty())
|
||||
{
|
||||
mTexCoords.resize(mPositions.size());
|
||||
mTexCoords0.resize(mPositions.size());
|
||||
}
|
||||
|
||||
// TODO: support more than one texcoord set (or no texcoords)
|
||||
mask |= LLVertexBuffer::MAP_TEXCOORD0;
|
||||
|
||||
if (!mTexCoords1.empty())
|
||||
{
|
||||
mask |= LLVertexBuffer::MAP_TEXCOORD1;
|
||||
}
|
||||
|
||||
if (mColors.empty())
|
||||
{
|
||||
mColors.resize(mPositions.size(), LLColor4U::white);
|
||||
}
|
||||
|
||||
mShaderVariant = 0;
|
||||
|
||||
// TODO: support colorless vertex buffers
|
||||
mask |= LLVertexBuffer::MAP_COLOR;
|
||||
|
||||
mShaderVariant = 0;
|
||||
|
||||
bool unlit = false;
|
||||
|
||||
// bake material basecolor into color array
|
||||
|
|
@ -332,6 +427,11 @@ bool Primitive::prep(Asset& asset)
|
|||
mShaderVariant |= LLGLSLShader::GLTFVariant::UNLIT;
|
||||
unlit = true;
|
||||
}
|
||||
|
||||
if (material.isMultiUV())
|
||||
{
|
||||
mShaderVariant |= LLGLSLShader::GLTFVariant::MULTI_UV;
|
||||
}
|
||||
}
|
||||
|
||||
if (mNormals.empty() && !unlit)
|
||||
|
|
@ -434,15 +534,17 @@ bool Primitive::prep(Asset& asset)
|
|||
}
|
||||
|
||||
// flip texcoord y, upload, then flip back (keep the off-spec data in vram only)
|
||||
for (auto& tc : mTexCoords)
|
||||
vertical_flip(mTexCoords0);
|
||||
mVertexBuffer->setTexCoord0Data(mTexCoords0.data());
|
||||
vertical_flip(mTexCoords0);
|
||||
|
||||
if (!mTexCoords1.empty())
|
||||
{
|
||||
tc[1] = 1.f - tc[1];
|
||||
}
|
||||
mVertexBuffer->setTexCoordData(mTexCoords.data());
|
||||
for (auto& tc : mTexCoords)
|
||||
{
|
||||
tc[1] = 1.f - tc[1];
|
||||
vertical_flip(mTexCoords1);
|
||||
mVertexBuffer->setTexCoord1Data(mTexCoords1.data());
|
||||
vertical_flip(mTexCoords1);
|
||||
}
|
||||
|
||||
|
||||
if (!mIndexArray.empty())
|
||||
{
|
||||
|
|
@ -453,10 +555,13 @@ bool Primitive::prep(Asset& asset)
|
|||
|
||||
mVertexBuffer->unbind();
|
||||
|
||||
Material& material = asset.mMaterials[mMaterial];
|
||||
if (material.mAlphaMode == Material::AlphaMode::BLEND)
|
||||
if (mMaterial != INVALID_INDEX)
|
||||
{
|
||||
mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND;
|
||||
Material& material = asset.mMaterials[mMaterial];
|
||||
if (material.mAlphaMode == Material::AlphaMode::BLEND)
|
||||
{
|
||||
mShaderVariant |= LLGLSLShader::GLTFVariant::ALPHA_BLEND;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -614,7 +719,7 @@ const LLVolumeTriangle* Primitive::lineSegmentIntersect(const LLVector4a& start,
|
|||
//create a proxy LLVolumeFace for the raycast
|
||||
LLVolumeFace face;
|
||||
face.mPositions = mPositions.data();
|
||||
face.mTexCoords = mTexCoords.data();
|
||||
face.mTexCoords = mTexCoords0.data();
|
||||
face.mNormals = mNormals.data();
|
||||
face.mTangents = mTangents.data();
|
||||
face.mIndices = nullptr; // unreferenced
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ namespace LL
|
|||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
|
||||
// CPU copy of mesh data, keep these as LLVector types for compatibility with raycasting code
|
||||
std::vector<LLVector2> mTexCoords;
|
||||
std::vector<LLVector2> mTexCoords0;
|
||||
std::vector<LLVector2> mTexCoords1;
|
||||
std::vector<LLVector4a> mNormals;
|
||||
std::vector<LLVector4a> mTangents;
|
||||
std::vector<LLVector4a> mPositions;
|
||||
|
|
|
|||
|
|
@ -549,10 +549,16 @@ void GLTFSceneManager::render(bool opaque, bool rigged, bool unlit)
|
|||
|
||||
void GLTFSceneManager::render(U8 variant)
|
||||
{
|
||||
// for debugging, just render the whole scene as opaque
|
||||
// by traversing the whole scenegraph
|
||||
// Assumes camera transform is already set and
|
||||
// appropriate shader is already boundd
|
||||
// just render the whole scene by traversing the whole scenegraph
|
||||
// Assumes camera transform is already set and appropriate shader is already bound.
|
||||
// Eventually we'll want a smarter render pipe that has pre-sorted the scene graph
|
||||
// into buckets by material and shader.
|
||||
|
||||
// HACK -- implicitly render multi-uv variant
|
||||
if (!(variant & LLGLSLShader::GLTFVariant::MULTI_UV))
|
||||
{
|
||||
render((U8) (variant | LLGLSLShader::GLTFVariant::MULTI_UV));
|
||||
}
|
||||
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
|
||||
|
|
@ -732,6 +738,7 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)
|
|||
F32 tf[8];
|
||||
material.mPbrMetallicRoughness.mBaseColorTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_BASE_COLOR_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::BASE_COLOR_TEXCOORD, material.mPbrMetallicRoughness.mBaseColorTexture.getTexCoord());
|
||||
|
||||
if (!LLPipeline::sShadowRender)
|
||||
{
|
||||
|
|
@ -748,15 +755,19 @@ void GLTFSceneManager::bind(Asset& asset, Material& material)
|
|||
|
||||
material.mNormalTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_NORMAL_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::NORMAL_TEXCOORD, material.mNormalTexture.getTexCoord());
|
||||
|
||||
material.mPbrMetallicRoughness.mMetallicRoughnessTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_METALLIC_ROUGHNESS_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::METALLIC_ROUGHNESS_TEXCOORD, material.mPbrMetallicRoughness.mMetallicRoughnessTexture.getTexCoord());
|
||||
|
||||
material.mOcclusionTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_OCCLUSION_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::OCCLUSION_TEXCOORD, material.mOcclusionTexture.getTexCoord());
|
||||
|
||||
material.mEmissiveTexture.mTextureTransform.getPacked(tf);
|
||||
shader->uniform4fv(LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM, 2, tf);
|
||||
shader->uniform1i(LLShaderMgr::EMISSIVE_TEXCOORD, material.mEmissiveTexture.getTexCoord());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ static bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader
|
|||
}
|
||||
|
||||
|
||||
static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool alpha_blend, bool rigged, bool unlit, bool use_sun_shadow)
|
||||
static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool alpha_blend, bool rigged, bool unlit, bool multi_uv, bool use_sun_shadow)
|
||||
{
|
||||
variant.mName = shader.mName.c_str();
|
||||
variant.mFeatures = shader.mFeatures;
|
||||
|
|
@ -271,6 +271,11 @@ static bool make_gltf_variant(LLGLSLShader& shader, LLGLSLShader& variant, bool
|
|||
variant.addPermutation("UNLIT", "1");
|
||||
}
|
||||
|
||||
if (multi_uv)
|
||||
{
|
||||
variant.addPermutation("MULTI_UV", "1");
|
||||
}
|
||||
|
||||
if (alpha_blend)
|
||||
{
|
||||
variant.addPermutation("ALPHA_BLEND", "1");
|
||||
|
|
@ -317,8 +322,9 @@ static bool make_gltf_variants(LLGLSLShader& shader, bool use_sun_shadow)
|
|||
bool alpha_blend = i & LLGLSLShader::GLTFVariant::ALPHA_BLEND;
|
||||
bool rigged = i & LLGLSLShader::GLTFVariant::RIGGED;
|
||||
bool unlit = i & LLGLSLShader::GLTFVariant::UNLIT;
|
||||
bool multi_uv = i & LLGLSLShader::GLTFVariant::MULTI_UV;
|
||||
|
||||
if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, unlit, use_sun_shadow))
|
||||
if (!make_gltf_variant(shader, shader.mGLTFVariants[i], alpha_blend, rigged, unlit, multi_uv, use_sun_shadow))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue