1

OpenGL で 3D パラメトリック サーフェスをレンダリングするためにvispyを使用しています。ほとんどの部分でうまく機能しているように見えますが、奇妙に見えます

法線が内側を向いているかのように、ジオメトリのエッジの周りの一部で()。

問題は、特にカメラ方向に対して垂直に近い領域で、フラグメント シェーダーまたはサーフェス法線のいずれかにあると思われます。頂点の作成方法は次のとおりです。

# --- Python imports ---
import numpy as np

# --- Internal imports ---
from glmesh import MeshApp3D

# -----------------------------------------------------------
# Torus parameters
radius1     = 1.0
radius2     = 0.2

# Define torus
torus       = ( lambda u,v : np.cos(u)*(radius1+radius2*np.cos(v)),
                lambda u,v : np.sin(u)*(radius1+radius2*np.cos(v)),
                lambda u,v : radius2*np.sin(v) )

# Generate grid of points on the torus
nSamples    = 100
U           = np.linspace(0.0,2*np.pi,nSamples)
V           = np.linspace(0.0,-2*np.pi,nSamples)

grid        = np.array( 
                        [
                            [ [torus[componentIndex](u,v) for u in U] for v in V ] for componentIndex in (0,1,2)
                        ],
                        dtype=np.float32 )


# -----------------------------------------------------------
# Rearrange grid to a list of points
vertices    = np.reshape(
                        np.transpose(   grid, 
                                        axes=(1,2,0)),
                        ( nSamples*nSamples ,3))

# Generate triangle indices in a positive permutation
# For example:
# 7---8---9
# | / | / |
# 4---5---6
# | / | / |
# 1---2---3
#
# (1,5,4) (1,2,5) (2,6,5) (2,3,6) (4,8,7) (4,5,8) (5,9,8) (5,6,9)

faces = np.zeros( ( 2*(nSamples-1)*(nSamples-1), 3 ), dtype=np.uint32 )
k = 0
for j in range(nSamples-1):
    for i in range(nSamples-1):
        jni = j*nSamples+i

        faces[k]    = [ jni, 
                        jni+nSamples+1, 
                        jni+nSamples ]

        faces[k+1]  = [ jni, 
                        jni+1, 
                        jni+1+nSamples ]
        k+=2


# -----------------------------------------------------------
# -----------------------------------------------------------
meshApp = MeshApp3D(    {'vertices' : vertices, 'faces' : faces},
                        colors=(1.0,1.0,1.0) )
meshApp.run()

フラグメント シェーダー:

varying vec3 position;
varying vec3 normal;
varying vec4 color;


void main() {

    // Diffuse
    vec3 lightDir       = normalize( position - vec3($lightPos) );
    float diffuse       = dot( normal, lightDir );
    //diffuse             = min( max(diffuse,0.0), 1.0 );

    // Specular
    vec3 halfWayVector  = normalize(  ( lightDir+vec3($cameraDir) )/2.0  );
    float specular      = min( max(   dot(halfWayVector,normal)   ,0.0), 1.0 );
    specular            = specular * specular * specular * specular;
    specular            = specular * specular * specular * specular;
    specular            = specular * specular * specular * specular;

    // Additive
    vec3 fragColor      = vec3($lightColor) * color.xyz;
    fragColor           = fragColor * ( $diffuseMaterialConstant * diffuse +
                                        $specularMaterialConstant * specular)
                                        + $ambientMaterialConstant * vec3($ambientLight) * color.xyz;


    gl_FragColor        = vec4(fragColor,1.0);
}

コードの残りの部分はモジュールに分割されていますが、簡単に言うと、次のようになります。

  • MeshDataは頂点と面から構築されます
  • 法線は、頂点の位置と、対応する三角形を定義する順序に基づいて、MeshData で内部的に生成されます。
  • キャンバスと OpenGL ウィンドウが作成され、初期化されます
  • メッシュは三角形のストリップとして描かれます

問題のある部分は、メッシュの三角形の定義です。例:

  7---8---9
  | / | / |
  4---5---6
  | / | / |
  1---2---3
v
^
|
---> u
(1,5,4) (1,2,5) (2,6,5) (2,3,6) (4,8,7) (4,5,8) (5,9,8) (5,6,9)

もともとは 2D 関数z=f(x,y)の三角形を生成するためのもので、うまく機能しましたが、パラメトリック サーフェスr(u,v) = [ x(u,v), y(u,v), z(u,v) ] . たとえば、これがパラメータv+2piではなく0から-2piになる理由です(そうしないと、法線が内側を向いてしまいます)。

画像に見られる不具合の原因について何か考えはありますか?

(または、より良い三角形の生成に関するアドバイスはありますか?)

4

0 に答える 0