編集: デモがついにオンラインになりました: 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 である必要があります。
私のエンジンの大きな違いの 1 つは、顔情報をクラス ( THREE.Face3 など) に保存せず、THREE.BufferGeometry のようにデータをバッファー属性に直接書き込むことを好むことです。
これまで、「Learning WebGL」コースのユタ ティーポット モデル、具体的にはこのリンクhttp://learningwebgl.com/blog/?p=1658のみを使用してきました。このモデルは私のエンジンで正確に機能し、おそらく THREE JSON 形式の初期バージョンです。頂点、texcoords などの json 配列を webgl バッファーに直接書き込むことにより、チュートリアルのようにそのモデルをロードします。これは私のエンジンで完全に機能しますが、最新のブレンダー エクスポーターからエクスポートされた単純なキューブでさえ、うまく機能していないようです。 .
どんな提案でも大歓迎です、ありがとう!
編集: webgl チュートリアルのティーポット モデルを使用した法線パスのスクリーンショット。注: THREE エクスポーターが壊れていることを示唆しているわけではなく、それを解析する私のコードです。私はこのエンジンで GBuffer の実装を過去 1 年ほどにわたって何度も調べてきましたが、今ではこれが正しいと確信しています。THREE json モデル形式を理解するのに少し問題があります。