编辑:演示终于上线了:http: //bharling.github.io/deferred/index.html使用下拉菜单切换到环面模型来现场查看问题。注意:需要 Webgl MRT 扩展。
我已经在 WebGL 中开发自己的延迟渲染引擎已有一段时间了,并且已经到了使用 GBuffers 和 MRT 扩展的工作原型的阶段,它可以非常令人满意地渲染一些茶壶。这是从头开始开发的,主要是为了让我在不使用任何框架的情况下正确学习 WebGL,并理解延迟渲染。对于任何感兴趣的人 - 来源在 github 上:https ://github.com/bharling/webgl-defer
我已经到了厌倦了只看到茶壶并尝试为 THREE.js JSON 格式模型实现加载器的阶段。我已经移植(复制)了加载器的主要部分,我可以让网格以正确的顶点和索引缓冲区出现,这很棒,但法线一直很混乱。我选择只支持带有顶点 UV 和顶点法线以及单一材质的索引几何体(最终这应该是基于 PBR 的),所以我忽略 JSON 中的任何其他内容,只将我支持的内容直接写入 Float32Arrays (等) . 下面是我的导入代码,以及我看到的奇怪法线的屏幕截图。
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
上面的屏幕截图应该是扩展的世界空间法线 gbuffer。
我的引擎的一大区别是我不将面部信息存储在类中(例如 THREE.Face3 ),而是将数据直接写入缓冲区属性,更像是 THREE.BufferGeometry。
到目前为止,我一直在使用“学习 WebGL”课程中的犹他茶壶模型,特别是这个链接http://learningwebgl.com/blog/?p=1658。这个模型在我的引擎中工作得很好,据说是三个 JSON 格式的早期版本。我通过将顶点、texcoords 等的 json 数组直接写入 webgl 缓冲区来加载该模型,这在我的引擎中非常有效,但即使是从最新的搅拌机导出器导出的简单立方体似乎也不能很好地工作.
任何建议都非常感谢,谢谢!
编辑:使用 webgl 教程中的茶壶模型的法线截图。注意:我并不是说三个导出器坏了,而是我解析它的代码。在过去一年左右的时间里,我在这个引擎中多次使用 GBuffer 实现,现在我很确定这是正确的,我只是在理解三种 json 模型格式时遇到了一些问题。