Javascript 解析THREE.json json网格格式法线错误
编辑:Demo finally online:使用下拉菜单切换到环面模型以查看问题的实况。注意:需要Webgl MRT扩展 我在WebGL中开发自己的延迟渲染引擎已经有一段时间了,现在我已经有了一个使用GBuffer和MRT扩展的工作原型,可以非常令人满意地渲染一些茶壶。这是从零开始开发的,主要是为了让我在不使用任何框架的情况下正确地学习WebGL,并理解延迟渲染。对于任何感兴趣的人-源代码位于github上: 我已经厌倦了只看茶壶,并尝试为三个JSON格式的模型实现一个加载器。我已经移植(复制)了加载程序的主要部分,我可以让网格显示正确的顶点和索引缓冲区,这很好,但法线总是扭曲的。我选择只支持带有顶点UV和顶点法线以及单个材质的索引几何体(最终这应该是基于PBR的),因此我忽略了JSON中的任何其他内容,只将我支持的内容直接写入Float32Array(等等)。下面是我的导入代码,加上我看到的奇怪法线的截图Javascript 解析THREE.json json网格格式法线错误,javascript,three.js,webgl,deferred-rendering,Javascript,Three.js,Webgl,Deferred Rendering,编辑:Demo finally online:使用下拉菜单切换到环面模型以查看问题的实况。注意:需要Webgl MRT扩展 我在WebGL中开发自己的延迟渲染引擎已经有一段时间了,现在我已经有了一个使用GBuffer和MRT扩展的工作原型,可以非常令人满意地渲染一些茶壶。这是从零开始开发的,主要是为了让我在不使用任何框架的情况下正确地学习WebGL,并理解延迟渲染。对于任何感兴趣的人-源代码位于github上: 我已经厌倦了只看茶壶,并尝试为三个JSON格式的模型实现一个加载器。我已经移植(复制
parseThreeJSModel: (data) =>
isBitSet = (value, position) ->
return value & ( 1 << position )
vertices = data.vertices
uvs = data.uvs
indices = []
normals = data.normals
vertexNormals = []
vertexUvs = []
vertexPositions = []
@vertexPositionBuffer = new DFIR.Buffer( new Float32Array( data.vertices ), 3, gl.STATIC_DRAW )
@vertexTextureCoordBuffer = new DFIR.Buffer( new Float32Array( data.uvs[0] ), 2, gl.STATIC_DRAW )
numUvLayers = data.uvs.length
faces = data.faces
zLength = faces.length
offset = 0
while offset < zLength
type = faces[offset++]
isQuad = isBitSet( type, 0 )
hasMaterial = isBitSet( type, 1 )
hasFaceVertexUv = isBitSet( type, 3 )
hasFaceNormal = isBitSet( type, 4 )
hasFaceVertexNormal = isBitSet( type, 5 )
hasFaceColor = isBitSet( type, 6 )
hasFaceVertexColor = isBitSet( type, 7 )
if isQuad
indices.push faces[ offset ]
indices.push faces[ offset + 1 ]
indices.push faces[ offset + 3 ]
indices.push faces[ offset + 1 ]
indices.push faces[ offset + 2 ]
indices.push faces[ offset + 3 ]
offset += 4
if hasMaterial
offset++
if hasFaceVertexUv
for i in [0 ... numUvLayers] by 1
uvLayer = data.uvs[i]
for j in [0 ... 4] by 1
uvIndex = faces[offset++]
u = uvLayer[ uvIndex * 2 ]
v = uvLayer[ uvIndex * 2 + 1 ]
if j isnt 2
vertexUvs.push u
vertexUvs.push v
if j isnt 0
vertexUvs.push u
vertexUvs.push v
if hasFaceNormal
offset++
if hasFaceVertexNormal
for i in [0 ... 4] by 1
normalIndex = faces[ offset++ ] * 3
normal = [ normalIndex++, normalIndex++, normalIndex ]
if i isnt 2
vertexNormals.push normals[normal[0]]
vertexNormals.push normals[normal[1]]
vertexNormals.push normals[normal[2]]
if i isnt 0
vertexNormals.push normals[normal[0]]
vertexNormals.push normals[normal[1]]
vertexNormals.push normals[normal[2]]
if hasFaceColor
offset++
if hasFaceVertexColor
offset += 4
else
indices.push faces[offset++]
indices.push faces[offset++]
indices.push faces[offset++]
if hasMaterial
offset++
if hasFaceVertexUv
for i in [0 ... numUvLayers] by 1
uvLayer = data.uvs[i]
for j in [0 ... 3] by 1
uvIndex = faces[offset++]
u = uvLayer[ uvIndex * 2 ]
v = uvLayer[ uvIndex * 2 + 1 ]
if j isnt 2
vertexUvs.push u
vertexUvs.push v
if j isnt 0
vertexUvs.push u
vertexUvs.push v
if hasFaceNormal
offset++
if hasFaceVertexNormal
for i in [0 ... 3] by 1
normalIndex = faces[ offset++ ] * 3
vertexNormals.push normals[normalIndex++]
vertexNormals.push normals[normalIndex++]
vertexNormals.push normals[normalIndex]
if hasFaceColor
offset++
if hasFaceVertexColor
offset +=3
@vertexNormalBuffer = new DFIR.Buffer( new Float32Array( vertexNormals ), 3, gl.STATIC_DRAW )
@vertexIndexBuffer = new DFIR.Buffer( new Uint16Array( indices ), 1, gl.STATIC_DRAW, gl.ELEMENT_ARRAY_BUFFER )
@loaded=true
jsmodel:(数据)=>
isBitSet=(值,位置)->
返回值&(1它不是问题的直接解决方案,但可能会有所帮助
如果您有像上面示例中的框一样的基本形状,您也可以同时使用THREE.FlatShading
和跳过设置法线。在某些情况下可能更容易:
var material = new THREE.???Material({ shading: THREE.FlatShading });
不确定您在Three.Face3到缓冲区之间的转换是否正确。这是我自己的Three Json解析器,我使用它从blender加载动画蒙皮网格,这可能会对您有所帮助。同样,只支持部分功能。它返回索引缓冲区,以便与.drawElements
而不是.drawArray一起使用s
function parsePackedArrayHelper(outArray, index, dataArray, componentSize){
for (var c = 0; c<componentSize; c++){
outArray.push(dataArray[index*componentSize + c]);
}
}
function parseThreeJson(geometry){
if (isString(geometry)){
geometry = JSON.parse(geometry);
}
var faces = geometry["faces"];
faces = convertQuadToTrig(faces); // can use the triangulate modifer in blender to skip this
// and others data etc...
var seenVertices = new Map();
var currentIndex = 0;
var maxIndex = 0;
var c = 0; // current index into the .faces array
while (c < faces.length){
var bitInfo = faces[c];
var hasMaterials = (bitInfo &(1<<1)) !== 0;
var hasVertexUvs = (bitInfo &(1<<3)) !== 0;
var hasVertexNormals = (bitInfo &(1<<5)) !== 0;
var faceIndex = c+1;
c += (
4 + //1 for the bitflag and 3 for vertex positions
(hasMaterials? 1: 0) +
(hasVertexUvs? 3: 0) +
(hasVertexNormals ? 3: 0)
);
for (var v = 0;v<3;v++){
var s = 0;
var vertIndex = faces[faceIndex+v];
var uvIndex = -1;
var normalIndex = -1;
var materialIndex = -1;
if (hasMaterials){
s += 1;
materialIndex = faces[faceIndex+3];
}
if (hasVertexUvs){
s += 3;
uvIndex = faces[faceIndex+s+v];
}
if (hasVertexNormals){
s += 3;
normalIndex = faces[faceIndex+s+v];
}
var hash = ""+vertIndex+","+uvIndex+","+normalIndex;
if (seenVertices.has(hash)){
indices[currentIndex++] = seenVertices.get(hash);
} else {
seenVertices.set(hash, maxIndex);
indices[currentIndex++] = maxIndex++;
parsePackedArrayHelper(verticesOut, vertIndex, verticesData, 3);
if (boneInfluences > 1){
// skinning data skipped
}
if (hasVertexUvs){
parsePackedArrayHelper(uvsOut, uvIndex, uvsData[0], 2);
// flip uv vertically; may or may not be needed
var lastV = uvsOut[uvsOut.length-1];
uvsOut[uvsOut.length-1] = 1.0 - lastV;
}
if (hasVertexNormals){
parsePackedArrayHelper(normalsOut, normalIndex, normalsData, 3);
}
if (hasMaterials){
materialIndexOut.push(materialIndex);
}
}
}
}
}
函数parsePackedArrayHelper(outArray、index、dataArray、componentSize){
对于(var c=0;cHave您是否首先确认问题在于json网格导入器,而不是您的g缓冲区或世界法线的渲染?您是否在blender中使用平滑或平面着色?我非常确定问题不在于我的gbuffer实现,正如我所说,我可以使用webgl教程网站和很好(我会试着在问题上附上一个截图).至于法线,我只是直接从混合器中导出默认立方体,因此法线应该是平坦的,而不是平滑的。我也尝试过导出suzanne,结果类似,网格和索引都很好,法线到处都是。感谢这一点-看起来很像我需要的,尽管我认为我真正需要的是e parsePackedArrayHelper()方法-你介意发布吗?谢谢!哦,抱歉-顶部没有看到!我会尝试一下,但我一定没有很好地解释它,因为我把索引缓冲区弄得一团糟(也就是说,法线看起来确实好一点)。将继续尝试,谢谢!谢谢-我实际上并没有使用three.js,事实上,这是我自己的引擎。我只是尝试使用three.js模型格式,而不是编写自己的,这在当时似乎是个好主意!@bharling解决您的问题有什么运气吗?还没有,不幸的是-我目前正在研究引擎的其他方面(并且忽略了它只能加载茶壶的事实:),它们现在看起来很漂亮。)现在考虑尝试使用.obj加载程序,这里有一些普通的webgl示例