如何在python上制作镜面照明以实现Phong照明?

如何解决如何在python上制作镜面照明以实现Phong照明?

我需要你的帮助。使用python,我必须通过phong模型实现我的三维形状的照明。我的图是一个三角形的二十四面体。我能够构建这个形状,找到顶点的坐标,还计算了每个面的法线。

我使用了 pygame、pyopengl。

为了实现 phong 光照模型,我设法制作了环境光照和漫射光照,但我不知道镜面光照使用什么函数

我尝试应用具有不同参数的 glMaterialfv() 等函数,但它对我不起作用。

这是我的代码

:

解决方法

您的代码中的所有内容都是正确的。使用旧的 OpenGL 固定功能管道,这是您可以获得的最佳结果。
固定函数管道使用 Blinn–Phong reflection model。但是,使用的是 Gouraud Shading 而不是 Phong Shading。虽然 Phong Shading 通常是指按片段执行光计算的技术,但在 Gouraud Shading 中,光计算是按顶点执行的。计算出的光沿(三角形)Primitives进行插值。
在镜面高光的情况下,光分布不是线性的,不能用线性插值计算。效果失真或完全消失。
请参阅 what the difference between phong shading and gouraud shading?OpenGL Lighting on texture plane is not working

可以通过将网格细分为小三角形来改善照明。这会导致为更多的点(顶点)计算光并且插值的影响较小。

如今,光是按片段计算的(Phong 着色)。为此,您需要实现一个 Shader 程序。见GLSL fixed function fragment program replacement

详细描述这一切对于单一的 Stack Overflow 答案来说太宽泛了。我建议阅读一个好的 OpenGL 教程。例如:Python Opengl(我最喜欢的是 C++ LearnOpenGL)。


要为您的特定遗留代码实现 Phong 着色,您需要编写一个 version 1.10 GLSL 着色器。有关一个很好的示例,请参阅 Per Fragment Lighting。您需要对着色器程序进行一些调整,以使颜色材料起作用。

顶点着色器

varying vec3 vN;
varying vec3 v;
varying vec4 color;
void main(void)  
{     
   v = vec3(gl_ModelViewMatrix * gl_Vertex);       
   vN = normalize(gl_NormalMatrix * gl_Normal);
   color = gl_Color;
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;  
}

片段着色器

varying vec3 vN;
varying vec3 v; 
varying vec4 color;
#define MAX_LIGHTS 1 
void main (void) 
{ 
   vec3 N = normalize(vN);
   vec4 finalColor = vec4(0.0,0.0,0.0);
   
   for (int i=0;i<MAX_LIGHTS;i++)
   {
      vec3 L = normalize(gl_LightSource[i].position.xyz - v); 
      vec3 E = normalize(-v); // we are in Eye Coordinates,so EyePos is (0,0) 
      vec3 R = normalize(-reflect(L,N)); 
   
      vec4 Iamb = gl_LightSource[i].ambient; 
      vec4 Idiff = gl_LightSource[i].diffuse * max(dot(N,L),0.0);
      Idiff = clamp(Idiff,1.0); 
      vec4 Ispec = gl_LightSource[i].specular * pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
      Ispec = clamp(Ispec,1.0); 
   
      finalColor += Iamb + Idiff + Ispec;
   }
   gl_FragColor = color * finalColor; 
}

使用 PyOpenGLs OpenGL.GL.shaders 模块编译和链接着色器:

def main():
    global surfaces,program

    pygame.init()
    display = (800,600)
    pygame.display.set_mode(display,DOUBLEBUF|OPENGL)
    clock = pygame.time.Clock()

    program = compileProgram( 
        compileShader(vertex_shader,GL_VERTEX_SHADER),compileShader(fragment_shader,GL_FRAGMENT_SHADER))

    # [...]

在绘制多边形之前安装着色器并启用照明,并在绘制线框之前禁用。例如:

def Cube():

    glEnable(GL_POLYGON_OFFSET_FILL)
    glPolygonOffset(1.0,1.0)
    glEnable(GL_LIGHTING)  

    glUseProgram(program)
    glBegin(GL_QUADS)
    for i_surface,surface in enumerate(surfaces):
        x = 0
        glNormal3fv(normals[i_surface])
        for vertex in surface:
            #x+=1
            glColor3fv(colors[x])
            glVertex3fv(verticies[vertex])
    glEnd()

    glDisable(GL_LIGHTING)
    glDisable(GL_POLYGON_OFFSET_FILL)

    glUseProgram(0)
    glColor3fv(colors[0])
    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glVertex3fv(verticies[vertex])
    glEnd()

完整示例:

import pygame
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GL.shaders import *

vertex_shader = """
varying vec3 vN;
varying vec3 v;
varying vec4 color;
void main(void)  
{     
   v = vec3(gl_ModelViewMatrix * gl_Vertex);       
   vN = normalize(gl_NormalMatrix * gl_Normal);
   color = gl_Color;
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;  
}
"""

fragment_shader = """
varying vec3 vN;
varying vec3 v; 
varying vec4 color;
#define MAX_LIGHTS 1 
void main (void) 
{ 
   vec3 N = normalize(vN);
   vec4 finalColor = vec4(0.0,1.0); 
   
      finalColor += Iamb + Idiff + Ispec;
   }
   gl_FragColor = color * finalColor; 
}
"""

verticies = (
    (0,- 0,1.15894198417663574),(0.63384598493576048,-0.63384598493576048,0.63384598493576048),(0.81949597597122192,0.81949597597122192),(1.15894198417663574,-0),0.81949597597122192,-0.81949597597122192),0.63384598493576048,-0.81949597597122192,0),(-0,(-0.81949597597122192,-0.63384598493576048),(0,-1.15894198417663574),1.15894198417663574,(-1.15894198417663574,(-0.63384598493576048,-1.15894198417663574,)

surfaces = (
    (20,21,25,12),(21,13,18),(17,24,14,16),(18,17),(16,10,4),(3,5,15,7),2,6,8),1,22),22,23,9),9,19,(13,11,12,25),(11,14),5),18,19),8,(7,20),(20,(9,(15,7,20,)

normals = [
    (-0.35740624923526854,-0.8628558767968414,-0.3574080425574267),(-0.8628548655932644,-0.3574083665235253,-0.3574083665235253),(-0.3574083665235253,0.8628548655932644,(-0.8628558767968414,0.3574080425574267,-0.35740624923526854),(0.3574080425574267,0.8628558767968414,(0.8628558767968414,-0.3574080425574267,(0.35740624923526854,0.8628558767968414),(-0.3574080425574267,-0.35740624923526854,(-0.35740624923526854,(-0.35740647831364963,-0.35740647831364963,-0.8628564298415289),-0.8628558767968414),0.35740624923526854,(-0.8628564298415289,0.35740647831364963,0.35740647831364963),0.3574083665235253),0.35740624923526854),(0.3574083665235253,-0.8628548655932644,0.3574080425574267),-0.3574080425574267)
]

colors = (
    (1,1),(1,)

edges = (
    (16,21),(4,3),2),13),(2,(8,(22,(5,11),15),(12,23),(23,24),(14,(25,6),(6,(10,10),(19,)


def Cube():

    glEnable(GL_POLYGON_OFFSET_FILL)
    glPolygonOffset(1.0,surface in enumerate(surfaces):
        x = 0
        glNormal3fv(normals[i_surface])
        for vertex in surface:
            #x+=1
            glColor3fv(colors[x])
            glVertex3fv(verticies[vertex])
    glEnd()

    glDisable(GL_LIGHTING)
    glDisable(GL_POLYGON_OFFSET_FILL)

    glUseProgram(0)
    glColor3fv(colors[0])
    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glVertex3fv(verticies[vertex])
    glEnd()


def main():
    global surfaces,GL_FRAGMENT_SHADER))

    glMatrixMode(GL_PROJECTION)
    gluPerspective(45,(display[0]/display[1]),0.1,50.0)

    glMatrixMode(GL_MODELVIEW)
    glTranslatef(0,-5)

    # Источник света - "от нас"
    glLight(GL_LIGHT0,GL_POSITION,0.4))
    # Ambient lighting
    glLightfv(GL_LIGHT0,GL_AMBIENT,(0.2,0.2,1))
    # Diffuse lighting
    glLightfv(GL_LIGHT0,GL_DIFFUSE,0.5,0))

#---------------------------------Specular Lighting------------It does not work!!!-----------
    glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,0))
    glMaterialf(GL_FRONT_AND_BACK,GL_SHININESS,128)
#--------------------------------------------------------------------------------------------

    glEnable(GL_DEPTH_TEST)

    while True:
        # Обрабатываем события
        for event in pygame.event.get():
            # Если нажимаем крестик на окошке - выходим
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        glEnable(GL_COLOR_MATERIAL)
        glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE)
        #glColorMaterial(GL_FRONT_AND_BACK,GL_SPECULAR)

        keys = pygame.key.get_pressed()

        if keys[pygame.K_LEFT]:
            glRotatef(5,0)
        elif keys[pygame.K_RIGHT]:
            glRotatef(-5,0)
        elif keys[pygame.K_UP]:
            glRotatef(5,0)
        elif keys[pygame.K_DOWN]:
            glRotatef(-5,0)

        Cube()

        glDisable(GL_LIGHT0)
        glDisable(GL_LIGHTING)
        glDisable(GL_COLOR_MATERIAL)

        pygame.display.flip()
        clock.tick(60)

if __name__ == '__main__':
    main()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?