聚光灯照射在平坦的表面上。

时间:2022-09-11 07:38:39

I want to shine a nice spotlight on a flat surface. I know that lighting is done per vertex and thus have create may vertices on the surface -- see this answer. However, I am getting these -- with GL_QUADS and GL_LINE_STRIP just to check that I have done things correctly.

我想把一个漂亮的聚光灯照在平坦的表面上。我知道照明是每一个顶点完成的,因此在表面上有可能的顶点——看这个答案。但是,我正在使用GL_QUADS和GL_LINE_STRIP来检查我是否做得正确。

聚光灯照射在平坦的表面上。聚光灯照射在平坦的表面上。

These are clearly rather poor. so,

这些国家显然相当贫穷。所以,

  • What need I chance so that the spotlight appears more like a circle on the surface?
  • 什么需要我的机会,使聚光灯看起来更像一个圆圈在表面?
  • How can I draw this scene faster?
  • 我怎么画得快一点?

Note: I realise that the normal calculation is not strictly necessary in this case but in a general case, it would be needed. Also, I could use a display list for the surface so it was only drawn once.

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

#!/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: I will update an answer with the source code using a shader when I have it working...

PS:当我有一个着色器时,我会用源代码更新一个答案……

1 个解决方案

#1


1  

Use a fragment shader to render the spotlight. This is also the fastest way you can render the scene because you won't be increasing tessellation, yet get the highest quality lighting.

使用碎片着色器渲染聚光灯。这也是你渲染场景的最快方式,因为你不会增加镶嵌,但会得到最高质量的照明。

Hope this helps!

希望这可以帮助!

#1


1  

Use a fragment shader to render the spotlight. This is also the fastest way you can render the scene because you won't be increasing tessellation, yet get the highest quality lighting.

使用碎片着色器渲染聚光灯。这也是你渲染场景的最快方式,因为你不会增加镶嵌,但会得到最高质量的照明。

Hope this helps!

希望这可以帮助!