2013-04-03 5 views
2

내 문제는 매우 간단합니다. LWJGL에서 법선을 그리면 초기화 후에 수동으로 업데이트 될 때까지 광원이 모델에만 적용됩니다. 내 코드합니다 (스탠포드 토끼 모델에서로드) 법선을 그리기위한거야 여기조명으로 LWJGL의 법선을 그립니다.

static Vector3f lightPosition = new Vector3f(-500f, -100f, 500f); 
GL11.glEnable(GL11.GL_LIGHTING); 
GL11.glEnable(GL11.GL_LIGHT0); 
GL11.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, asFloatBuffer(new float[]{0.05f, 0.05f, 0.05f, 1f})); 
GL11.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, asFloatBuffer(new float[]{1.5f, 1.5f, 1.5f, 1f})); 

그리고 :

for (Face f : bunnyModel.faces){ 
Vector3f n1 = bunnyModel.normals.get((int)f.normal.x - 1); 
GL11.glNormal3f(n1.x, n1.y, n1.z); 
Vector3f v1 = bunnyModel.vertices.get((int)f.vertex.x - 1); 
GL11.glVertex3f(v1.x, v1.y, v1.z); 
Vector3f n2 = bunnyModel.normals.get((int)f.normal.y - 1); 
GL11.glNormal3f(n2.x, n2.y, n2.z); 
Vector3f v2 = bunnyModel.vertices.get((int)f.vertex.y - 1); 
GL11.glVertex3f(v2.x, v2.y, v2.z); 
Vector3f n3 = bunnyModel.normals.get((int)f.normal.z - 1); 
GL11.glNormal3f(n3.x, n3.y, n3.z); 
Vector3f v3 = bunnyModel.vertices.get((int)f.vertex.z - 1); 
GL11.glVertex3f(v3.x, v3.y, v3.z); 
} 

내가 잘못 여기서 뭐하는 거지 여기에 조명 초기화입니까? 법선을 비활성화하면 라이팅은 모델을 제외한 모든 것에 잘 작동합니다. 그러나 내가 그들을 가능하게하면 토끼는 빛을 받지만 다른 표면은 빛을 얻지 못합니다.

+0

다른 표면에도 법선이 있습니까? 또는 아마도 내부를 가리키는 법선일까요? – Abaab

+0

아니요, 유일한 법선은 모델 내에 포함됩니다. – caseif

+0

씬의 법선 만 모델의 법선이면, 나머지 장면은 법선없이 올바르게 조명되지 않습니다. – Abaab

답변

2

OpenGL에서 조명이 활성화되면 모든 다각형은 법선에 따라 켜집니다. 폴리곤에 법선이 주어지지 않으면 해당 객체의 법선은 vec3 {0, 0, 1}으로 기본 설정됩니다. 기본적으로 조명을 활성화하고 모델을 그린 다음 조명을 비활성화하고 나머지 장면을 그립니다. 당 얼굴 법선을 계산

여기에, 꽤 쉽게 내가 쓴 조금 getNormal() 함수입니다 :

//Feel free to use this for whatever you want, no licenses applied or anything. 

//p1, p2, p3 - Vertices of triangle 
public Vector3f getNormal(Vector3f p1, Vector3f p2, Vector3f p3) { 

    //Create normal vector we are going to output. 
    Vector3f output = new Vector3f(); 

    //Calculate vectors used for creating normal (these are the edges of the triangle). 
    Vector3f calU = new Vector3f(p2.x-p1.x, p2.y-p1.y, p2.z-p1.z); 
    Vector3f calV = new Vector3f(p3.x-p1.x, p3.y-p1.y, p3.z-p1.z); 

    //The output vector is equal to the cross products of the two edges of the triangle 
    output.x = calU.y*calV.z - calU.z*calV.y; 
    output.y = calU.z*calV.x - calU.x*calV.z; 
    output.z = calU.x*calV.y - calU.y*calV.x; 

    //Return the resulting vector. 
    return output.normalise(); 
} 

[OpenGL Documentation]

[Another similar question]

[More on the cross product]

는하지만 ... 얼굴마다의 법선은 일종의 ... 나쁜 것처럼 보일 수 있습니다. 더 매끄러운 결과를 원하면 정점 별 법선을 사용해야합니다. 당 얼굴

: 당 정점 You can see the triangles...

: 여기에 차이점 enter image description here

큐브 같은 것들에 대한 당 얼굴 법선을 사용하지 있는지 확인이 큐브 곡선, 평면하지 않습니다. Per-Vertex 법선은 무언가를 더욱 부드럽고 현실감있게 보이고 싶어하는 상황 (피부, 감자, 베개 등)에서 사용됩니다. 당 정점 법선을 계산하기 위해

, 그래서 같은 결합 된 다각형의 당신이 기본적으로 평균 모든 법선 :

It's de average

당신이 검은 완전히 찾고 모델을 얻을 일 경우

또는 직면하고있는 부분은 보이지 않습니다 getNormal() 함수에 점을 넣는 순서를 반대로 시도하십시오 (또는 법선을 부정하면 오류는 법선이 바깥 쪽이 아닌 안쪽을 향하고 있다는 사실에 기인합니다).

도움이 되셨습니다.

+0

훌륭한 답변이지만, 대신 사변형의 법선을 계산하기 위해 포함 된 메서드를 수정하는 방법은 무엇입니까? – caseif

+0

@mproncace 쿼드가 "평면"인 경우 쿼드의 첫 번째 3 점을 getNormal() 함수에 넣기 만하면됩니다. 그렇지 않으면 4 점 p1, p2, p3 및 p4가 주어지면 정규화 된 벡터는 (getNormal (p1, p2, p3) + getNormal (p2, p3, p4)) normalize()입니다. wen OpenGL은 쿼드를 그립니다. 실제로는 2 개의 삼각형을 그립니다. 그래픽 카드는 삼각형 그리기 용으로 설계되었습니다. 아, 또한 getNormal() 함수 (출력 벡터를 정규화하는 것으로 기억)를 수정 했으므로 복사 한 경우 붙여 넣기를 다시해야합니다. – Abaab

+0

@mproncace GLSL을 아직 사용하고 계십니까? 나는이 질문을 새로운 질문에 좀 더 많은 정보를 넣어 주길 바란다. – Abaab