SharpGL中gl.Color()无效无法绘制自定义颜色球体问题排查
问题背景
我正在使用SharpGL开展图形开发工作。
我尝试绘制三个相互重叠、分别采用三种不同颜色的球体,预期实现效果如下:
实际运行后得到的输出效果如下:
代码中调用的gl.Color()方法对绘制的物体完全不生效。
- 如何修复该问题?
问题根因
初始化代码中开启了GL_LIGHTING光照模式,默认状态下,开启光照后OpenGL的渲染颜色完全由材质参数决定,gl.Color()设置的顶点颜色不会参与光照计算,因此设置的红、绿、蓝三色都没有生效,所有球体使用初始化时设置的默认材质渲染,显示为统一的浅色。
修复方案
在Init方法的光照配置段添加两行代码,启用颜色材质跟踪即可,代码放在gl.Enable(OpenGL.GL_LIGHT0);语句之后:
gl.Enable(OpenGL.GL_COLOR_MATERIAL); gl.ColorMaterial(OpenGL.GL_FRONT, OpenGL.GL_AMBIENT_AND_DIFFUSE);
配置说明:
GL_COLOR_MATERIAL:启用后gl.Color()设置的颜色会自动同步到指定的材质属性,不需要每次绘制物体都手动调用gl.Material()修改材质颜色- 第二行代码配置物体正面的环境光、漫反射属性跟随
gl.Color()的值变化,是最常用的颜色材质配置,足够实现预期的彩色球体光照效果。
问题复现完整源代码
public static class OpenGLhelper { public static void Init(OpenGL gl) { float[] mat_specular = { 1.0f, 1.0f, 1.0f, 1.0f }; float[] mat_shininess = { 50.0f }; float[] light_position = { 0.5f, 0.5f, 0.750f, 0.0f }; gl.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); gl.ShadeModel(OpenGL.GL_SMOOTH); gl.Material(OpenGL.GL_FRONT, OpenGL.GL_SPECULAR, mat_specular); gl.Material(OpenGL.GL_FRONT, OpenGL.GL_SHININESS, mat_shininess); gl.Light(OpenGL.GL_LIGHT0, OpenGL.GL_POSITION, light_position); gl.Enable(OpenGL.GL_LIGHTING); gl.Enable(OpenGL.GL_LIGHT0); gl.Enable(OpenGL.GL_DEPTH_TEST); // 修复代码:取消下方两行注释即可让gl.Color()生效 // gl.Enable(OpenGL.GL_COLOR_MATERIAL); // gl.ColorMaterial(OpenGL.GL_FRONT, OpenGL.GL_AMBIENT_AND_DIFFUSE); //// Cull back faces. gl.Enable(OpenGL.GL_CULL_FACE); gl.CullFace(OpenGL.GL_BACK); gl.FrontFace(OpenGL.GL_CW); } private static void drawSphere(OpenGL gl, Point3d c, Rgb color, double r, int n) { int i, j; double theta1, theta2, theta3; Point3d e = new Point3d(); Point3d p = new Point3d(); if (c == null) { c = new Point3d(0, 0, 0); } double twoPi = Math.PI * 2; double piD2 = Math.PI / 2; if (r < 0) r = -r; if (n < 0) n = -n; if (n < 4 || r <= 0) { gl.Begin(OpenGL.GL_POINTS); gl.Color(color.Red, color.Green, color.Blue); gl.Vertex(c.X, c.Y, c.Z); gl.End(); return; } for (j = 0; j < n / 2; j++) { theta1 = j * twoPi / n - piD2; theta2 = (j + 1) * twoPi / n - piD2; gl.Begin(OpenGL.GL_QUAD_STRIP); for (i = 0; i <= n; i++) { theta3 = i * twoPi / n; e.X = Math.Cos(theta2) * Math.Cos(theta3); e.Y = Math.Sin(theta2); e.Z = Math.Cos(theta2) * Math.Sin(theta3); p.X = c.X + r * e.X; p.Y = c.Y + r * e.Y; p.Z = c.Z + r * e.Z; gl.Normal(e.X, e.Y, e.Z); gl.TexCoord(i / (double)n, 2 * (j + 1) / (double)n); gl.Color(color.Red, color.Green, color.Blue); gl.Vertex(p.X, p.Y, p.Z); e.X = Math.Cos(theta1) * Math.Cos(theta3); e.Y = Math.Sin(theta1); e.Z = Math.Cos(theta1) * Math.Sin(theta3); p.X = c.X + r * e.X; p.Y = c.Y + r * e.Y; p.Z = c.Z + r * e.Z; gl.Normal(e.X, e.Y, e.Z); gl.TexCoord(i / (double)n, 2 * j / (double)n); gl.Color(color.Red, color.Green, color.Blue); gl.Vertex(p.X, p.Y, p.Z); } gl.End(); } } public static void Display(OpenGL gl) { gl.Clear(OpenGL . GL_COLOR_BUFFER_BIT | OpenGL . GL_DEPTH_BUFFER_BIT); drawSphere(gl, new Point3d(0, 0, 0), new Rgb(1, 0, 0), 0.5, 20); drawSphere(gl, new Point3d(0, 0.5, 0), new Rgb(0, 1, 0), 0.5, 20); drawSphere(gl, new Point3d(0, -0.5, 0), new Rgb(0, 0, 1), 0.5, 20); gl.Flush(); } public static void Reshape(OpenGL gl, int width, int height) { } } public partial class SharpGLForm : Form { private float rotation = 0.0f; public SharpGLForm() { InitializeComponent(); OpenGL gl = openGLControl1.OpenGL; OpenGLhelper.Init(gl); } private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e) { OpenGL gl = openGLControl1.OpenGL; gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); gl.LoadIdentity(); gl.Translate(0.0f, 0.0f, -4.0f); // Move into the screen gl.Rotate(rotation, 0.0f, 1.0f, 0.0f); OpenGLhelper.Display(gl); rotation += 3.0f; } }
内容的提问来源于stack exchange,提问作者user366312
相关产品推荐
相关产品推荐

