如何解决如何在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 举报,一经查实,本站将立刻删除。