You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:18:35