聚光灯照耀在平坦的表面上

时间:2012-07-05 14:55:56

标签: python opengl

我想在平坦的表面上照亮好聚光灯。我知道每个顶点完成光照,因此在表面上创建了可能的顶点 - 请参阅此answer。但是,我得到了这些 - 用GL_QUADS和GL_LINE_STRIP来检查我是否已经正确地完成了任务。

enter image description here enter image description here

这些显然相当差。所以,

  • 我需要什么机会让聚光灯看起来更像是表面上的圆圈?
  • 如何更快地绘制此场景?

注意:我意识到在这种情况下,正常的计算并不是绝对必要的,但在一般情况下,需要它。此外,我可以使用表面的显示列表,因此它只绘制一次。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from OpenGL.GLUT import *
from OpenGL.GL import *
from OpenGL.GLU import *
import numpy as np
from Numeric import *

lightPosition = np.array([10, 30, 20, 1])
view_rotation = np.array([0, 0, 0])

def init():
    globAmb = [0.3, 0.3, 0.3, 1.0]
    lightAmb = [0.0, 0.0, 0.0, 1.0]
    lightDifAndSpec = [0.7, 0.7, 0.7, 1.0]

    glutInit()

    glClearColor(0.0, 0.0, 0.0, 0.0)

    glEnable(GL_DEPTH_TEST)
    glClearDepth(1.0)
    glDepthFunc(GL_LESS)

    glShadeModel(GL_SMOOTH)

    glEnable(GL_LIGHTING)
    glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb)
    glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDifAndSpec)
    glLightfv(GL_LIGHT0, GL_SPECULAR, lightDifAndSpec)
    glEnable(GL_LIGHT0)
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globAmb)
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE)

    glEnable(GL_CULL_FACE)
    glCullFace(GL_BACK)


def display():
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    glLoadIdentity()
    gluLookAt(0.0, 40.0, 40.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

    glRotatef(view_rotation[0], 1.0, 0.0, 0.0)
    glRotatef(view_rotation[1], 0.0, 1.0, 0.0)
    glRotatef(view_rotation[2], 0.0, 0.0, 1.0)

    glPushMatrix()
    pos = [0, 20, 0, 1]
    direction = [0.0, -1.0, 0.0]
    spotAngle = 20
    glLightfv(GL_LIGHT0, GL_POSITION, pos)
    glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, spotAngle)
    glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, direction)
    glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2)

    glPushMatrix();
    glDisable(GL_LIGHTING)
    glTranslate(pos[0], 0.5* pos[1], pos[2])
    glRotatef(-90.0, 1.0, 0.0, 0.0)
    glColor3f(1.0, 1.0, 1.0)
    PI = 3.141592
    glutWireCone(3.0 * np.tan( spotAngle/180.0 * PI ), pos[1], 10, 6)
    glEnable(GL_LIGHTING)
    glPopMatrix();

    draw_cube()

    glPopMatrix()
    glFlush ()


def reshape(w, h):
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45.0, float(w) / float(h), 0.1, 100.0)
    glMatrixMode(GL_MODELVIEW)


def keyboard(key, x, y):
    if key == chr(27):
        sys.exit(0)
    elif key == 'w':
        view_rotation[0] += 10
        display()
    elif key == 's':
        view_rotation[0] -= 10
        display()
    elif key == 'a':
        view_rotation[1] -= 10
        display()
    elif key == 'd':
        view_rotation[1] += 10
        display()
    else:
        print "Unknown %s key" %(key)

def draw_cube ():
    glPushMatrix()
    glRotatef(45, 0, 1, 0)
    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, [183/256.0, 65/256.0, 14/256.0, 1.0]);
    glMaterialfv(GL_FRONT, GL_SPECULAR, [1, 1, 1, 1]);
    glMaterialfv(GL_FRONT, GL_SHININESS, [100.0]);
    sz = 10
    step = 1
    for x in arange(-sz, sz, step):
        for z in arange(-sz, sz, step):

            v0 = np.array([x,  sz, z])
            v1 = np.array([x,  sz, z+step])
            v2 = np.array([x+step,  sz, z+step])
            v3 = np.array([x+step,  sz, z])

            #glBegin(GL_QUADS) # Uncomment to get the surface instead of lines.
            glBegin(GL_LINE_STRIP)

            n = get_normal_vector(v0, v1, v3)
            glNormal(n[0], n[1], n[2])
            glVertex3f(v0[0], v0[1], v0[2])

            n = get_normal_vector(v1, v2, v0)
            glNormal(n[0], n[1], n[2])
            glVertex3f(v1[0], v1[1], v1[2])

            n = get_normal_vector(v2, v3, v1)
            glNormal(n[0], n[1], n[2])
            glVertex3f(v2[0], v2[1], v2[2])

            n = get_normal_vector(v3, v0, v2)
            glNormal(n[0], n[1], n[2])
            glVertex3f(v3[0], v3[1], v3[2])
            glEnd()

    glPopMatrix()




def get_normal_vector (v1, v2, v3):
    v = np.cross(v2-v1, v3-v1)
    n = np.sqrt(np.dot(v, v.conj()))
    if n:
        return v/n 
    else:
        print v1
        print v2
        print v3
        print v/n
        sys.exit(-1)


glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
glutInitWindowSize(800, 800)
glutInitWindowPosition(300, 0)
glutCreateWindow('Lines')
init()
glutDisplayFunc(display)
glutReshapeFunc(reshape)
glutKeyboardFunc(keyboard)
glutMainLoop()

PS:我将使用着色器更新源代码的答案...

1 个答案:

答案 0 :(得分:1)

使用fragment shader to render the spotlight。这也是您渲染场景的最快方式,因为您不会增加曲面细分,同时获得最高质量的光照。

希望这有帮助!