反射模型在使用 glColor3f 的 OpenGl 中无法正常工作

Reflection model does not work correctly in OpenGl using glColor3f

我有一张 480x640 二维双阵列深度图。我使用 glBegin(GL_TRIANGLES) 使用 openGL 将其可视化。 这是我的代码,它工作正常:

int main(int argc, char** argv){


ifstream ifs("D:\DepthMaps1-20\DepthMap_1.dat", std::ios::binary);
if (ifs) {
    double dheight, dwidth;

    
    ifs.read(reinterpret_cast<char*>(&dheight), sizeof dheight);
    ifs.read(reinterpret_cast<char*>(&dwidth), sizeof dwidth);

    
    height = static_cast<size_t>(dheight);
    width = static_cast<size_t>(dwidth);

    
    vector<vector<double>> dmap(height, vector<double>(width));

    
    for (auto& row : dmap) {
        for (double& col : row)
            ifs.read(reinterpret_cast<char*>(&col), sizeof col);
    }

    double fx = 525.0;
    double fy = 525.0; // default focal length
    double cx = 319.5;
    double cy = 239.5; // default optical center

    vector<vector<double>> x(height, vector<double>(width));
    vector<vector<double>> y(height, vector<double>(width));
    vector<vector<double>> z(height, vector<double>(width));

    
    for (unsigned i = 0; i < dmap.size(); i++)
    {
        for (unsigned j = 0; j < dmap[i].size(); j++)
        {
            z[i][j] = dmap[i][j] / 500.0;
            x[i][j] = (j - cx) * z[i][j] / fx;
            y[i][j] = (i - cy) * z[i][j] / fy;
        }

    }
    
    
    GLFWwindow * window;

    
    if (!glfwInit())
        return -1;

    
    window = glfwCreateWindow(640, 640, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    
    glfwMakeContextCurrent(window);

    
    glfwSetKeyCallback(window, keyCallback);
    
    while (!glfwWindowShouldClose(window))
    {

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glLoadIdentity();

        glBegin(GL_TRIANGLES);

        glColor3f(189.0/255.0, 140.0 / 255.0, 194.0 / 255.0);
        for (unsigned i = 0; i < dmap.size(); i++)
        {
            for (unsigned j = 0; j < dmap[i].size(); j++)
            {
                if (j < dmap[i].size() - 2 && i < dmap.size() - 2)
                {
                    if (z[i][j] != 0 && z[i][j + 1] != 0 && z[i + 1][j] != 0 && z[i + 1][j+1] != 0)
                    {
                        glVertex3d(x[i][j], y[i][j], z[i][j]);
                        glVertex3d(x[i][j + 1], y[i][j + 1], z[i][j + 1]);
                        glVertex3d(x[i + 1][j], y[i + 1][j], z[i + 1][j]);

                        glVertex3d(x[i][j+1], y[i][j+1], z[i][j+1]);
                        glVertex3d(x[i + 1][j + 1], y[i + 1][j + 1], z[i + 1][j + 1]);
                        glVertex3d(x[i + 1][j], y[i + 1][j], z[i + 1][j]);

                    }
                }
            }
        }
        glEnd();

        glFlush();

        glfwSwapBuffers(window);
        glfwPollEvents();

    }
    ifs.close();

}

return 0;}

所以现在我需要使用数学公式为反射模型添加光照。想法是 - 照明被视为具有相同强度的平行(单向)光束,光源的大小不受限制。照明由方向 L [Lx Ly Lz] 设置。 这是我的 Lambert 反射模型代码,它可以工作,但我想要更好的结果。

float coord = -1.0f;
float coord1 = -1.0f;
float coord2 = -0.0f;
float coord4 = -1.0f;
float coord5 = -2.0f;
float coord6 = -1.0f;


int main(int argc, char** argv)
{
    
    ifstream ifs("D:\DepthMaps1-20\DepthMap_1.dat", std::ios::binary);
    if (ifs) {
        double dheight, dwidth;

        ifs.read(reinterpret_cast<char*>(&dheight), sizeof dheight);
        ifs.read(reinterpret_cast<char*>(&dwidth), sizeof dwidth);

        height = static_cast<size_t>(dheight);
        width = static_cast<size_t>(dwidth);

        
        vector<vector<double>> dmap(height, vector<double>(width));

        
        for (auto& row : dmap) {
            for (double& col : row)
                ifs.read(reinterpret_cast<char*>(&col), sizeof col);
        }

        double fx = 525.0;
        double fy = 525.0; // default focal length
        double cx = 319.5;
        double cy = 239.5; // default optical center

        vector<vector<double>> x(height, vector<double>(width));
        vector<vector<double>> y(height, vector<double>(width));
        vector<vector<double>> z(height, vector<double>(width));

        vector<vector<int>> brightness(height, vector<int>(width));

        
        for (unsigned i = 0; i < dmap.size(); i++)
        {
            for (unsigned j = 0; j < dmap[i].size(); j++)
            {
                z[i][j] = dmap[i][j] / 500.0;
                x[i][j] = (j - cx) * z[i][j] / fx;
                y[i][j] = (i - cy) * z[i][j] / fy;
    
            }

        }
        
        
        GLFWwindow * window;

        
        if (!glfwInit())
            return -1;

        
        window = glfwCreateWindow(640, 640, "Hello World", NULL, NULL);
        if (!window)
        {
            glfwTerminate();
            return -1;
        }

        
        glfwMakeContextCurrent(window);

    
        glfwSetKeyCallback(window, keyCallback);
        
        while (!glfwWindowShouldClose(window))
        {

            glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            glLoadIdentity();


            glRotatef(tippangle, 1, 0, 0);  
            glRotatef(viewangle, 0, 1, 0);  

            glScalef(scaleF, scaleF, scaleF);
            

            //x
            glRasterPos3f(1.1, 0.0, 0.0);
            //y
            glRasterPos3f(0.0, 1.1, 0.0);

            //z
            glRasterPos3f(0.0, 0.0, 1.1);

            glTranslatef(d[0], d[1], d[2]);   

            glBegin(GL_TRIANGLES);

            
            for (unsigned i = 0; i < dmap.size(); i++)
            {
                for (unsigned j = 0; j < dmap[i].size(); j++)
                {
                    if (j < dmap[i].size() - 2 && i < dmap.size() - 2)
                    {
                        if (z[i][j] != 0 && z[i][j + 1] != 0 && z[i + 1][j] != 0 && z[i + 1][j + 1] != 0)
                        {
                            


                            //Determination of the normal
                            glm::vec3 left = glm::vec3(0, 1, (z[i][j + 1] - z[i][j+1]));
                            glm::vec3 right = glm::vec3(1, 0, (z[i + 1][j] - z[i + 1][j]));
                            
                            glm::vec3 normal = glm::normalize(glm::cross(left, right));


                        
                            glm::vec3 Position_Light = glm::vec3(coord + 0, coord1+ 0, coord2 + 0); //Light source
                            glm::vec3 Position_View = glm::vec3(coord4, coord5, coord6); //observer
                            glm::vec3 Position_Point = glm::vec3(x[i][j], y[i][j], z[i][j]);


                    

                            //Directions
                            glm::vec3 Light_Direction = glm::normalize(Position_Light - Position_Point); //To source 
                            glm::vec3 View_Direction = glm::normalize(Position_View - Position_Point); // To the observer
                            glm::vec3 HalfWay_Direction = glm::normalize(Light_Direction + View_Direction); //Median vector (halfway)

                            double kd = 1;//diffuse reflectance for the Lambert model 
                            double I = 0; //variable brightness

                            
                            I = kd * glm::dot(Light_Direction, normal);

                            glColor3f(I, I, I);
                            glVertex3d(x[i][j], y[i][j], z[i][j]);
                            glVertex3d(x[i][j + 1], y[i][j + 1], z[i][j + 1]);
                            glVertex3d(x[i + 1][j], y[i + 1][j], z[i + 1][j]);

                            glVertex3d(x[i][j+1], y[i][j+1], z[i][j+1]);
                            glVertex3d(x[i + 1][j + 1], y[i + 1][j + 1], z[i + 1][j + 1]);
                            glVertex3d(x[i + 1][j], y[i + 1][j], z[i + 1][j]);
                            
                        }
                    }
                }
            }
            glEnd();

            glFlush();

            glfwSwapBuffers(window);
            glfwPollEvents();

        }
        ifs.close();
    }

    return 0;
}

这是我的结果。

我想要这个结果。

第二个结果是这项工作的示例,但使用的是 c#。源代码在这里:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        double[,] depth;
        int[,] brightness;
        bool glConrerolIsLoaded; 
        
        float coord = 501.5f;
        float coord1 = -17.5f;
        float coord2 = -2979.5f;
        float coord4 = -73.0f;
        float coord5 = 1269.0f;
        float coord6 = 413.5f; 

        int resNum = 0; 

        private void glControl1_Load(object sender, EventArgs e)
        {
            glConrerolIsLoaded = true;
            GL.ClearColor(Color.Black);        
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {            
            glControl1.Invalidate();
            panel1.Invalidate();
        }

        private void numericUpDown2_ValueChanged(object sender, EventArgs e)
        {           
            glControl1.Invalidate();
            panel1.Invalidate();
        }

        private void numericUpDown3_ValueChanged(object sender, EventArgs e)
        {
            glControl1.Invalidate();
            panel1.Invalidate();
        }


        

private void glControl1_Paint(object sender, PaintEventArgs e)
        {      

            GL.LoadIdentity();
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.Viewport(0, 0, glControl1.Width, glControl1.Height);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();
            Matrix4 perspectiveMatrix = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45), glControl1.Width / glControl1.Height, 1.0f, 100.0f);
            GL.LoadMatrix(ref perspectiveMatrix);
            GL.MatrixMode(MatrixMode.Modelview);

            GL.Translate(-25.0, -9.0, -45.0);
            GL.Scale(0.04, 0.04, 0.04); 

            GL.Begin(BeginMode.Points);

            for (int i = 0; i < depth.GetLength(0) - 1 ; i++)
            {
                for (int j = 0; j < depth.GetLength(1) - 1 ; j++)
                {
                    if (depth[i, j] != 0 && depth[i + 1, j] != 0 && /*depth[i + 1, j + 1] != 0 &&*/ depth[i, j + 1] != 0)
                    {   
                        
                        Vector3 left = new Vector3(0, 1, Convert.ToSingle(depth[i, j + 1]) - Convert.ToSingle(depth[i, j]));
                        Vector3 right = new Vector3(1, 0, Convert.ToSingle(depth[i + 1, j]) - Convert.ToSingle(depth[i, j]));
                        Vector3 Normal = Vector3.Normalize(Vector3.Cross(left, right));

                        
                        Vector3 Position_Light = new Vector3(coord + Convert.ToSingle(numericUpDown1.Value), coord1 
                            + Convert.ToSingle(numericUpDown2.Value), coord2 + Convert.ToSingle(numericUpDown3.Value));
                        Vector3 Position_View = new Vector3(coord4, coord5, coord6);
                        Vector3 Position_Point = new Vector3(i, j, Convert.ToSingle(depth[i, j]));

                        
                        Vector3 Light_Direction = Vector3.Normalize(Position_Light - Position_Point);                  
                        Vector3 View_Direction = Vector3.Normalize(Position_View - Position_Point);
                        Vector3 HalfWay_Direction = Vector3.Normalize(Light_Direction + View_Direction); 

                        double kd = 1;
                       
                        double I = 0; 


                      
                            I = kd * Vector3.Dot(Light_Direction, Normal);
    
                        GL.Color3(I, I, I);
                        GL.Vertex3(i, j, depth[i, j]);

                        
                }                
            }            

            GL.End();

            glControl1.SwapBuffers();
        }
       
        private void Form1_Load(object sender, EventArgs e)//Считывание карты глубины
        {            
            string path = @"DepthMap_1.dat";
            BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open));            
            double Height1 = reader.ReadDouble();
            double Width1 = reader.ReadDouble();
            depth = new double[Convert.ToInt16(Height1), Convert.ToInt16(Width1)];
            brightness = new int[Convert.ToInt16(Height1), Convert.ToInt16(Width1)];
            for (int i = 0; i < depth.GetLength(0); i++)
            {
                for (int j = 0; j < depth.GetLength(1); j++)
                {
                    depth[i, j] = reader.ReadDouble();
                }
            }
            reader.BaseStream.Close();
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        { 
        }
    }
}

所以我的问题是我的代码有什么不正确的地方?如果灯位置不好请帮我修一下

颜色由环境光+漫反射+镜面反射组成。镜面反射分量会增加反射,我认为这是您所期望的。您正在为颜色

进行的计算
I_diffuse = kd * glm::dot(Light_Direction, normal); 

只是漫反射分量。 所以你需要的是

I_total = I_diffuse + I_specular;

你已经有I_diffuse,你可以得到I_specular如下,

vec3 viewDir = normalize(viewPos - pointPos);

vec3 reflectDir = reflect(-lightDir, normal); 

float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);

vec3 I_specular = specularStrength * spec * Ks;

specularStrength 可用于控制反射强度。

注意: 您正在使用的代码看起来像是在一个固定功能的管道中,它已被弃用。如果可能,请将其移至带有着色器的可编程管线。 您可以关注:https://learnopengl.com/Lighting/Basic-Lighting

我找到了答案,我在这里弄错了:

//Determination of the normal
glm::vec3 left = glm::vec3(0, 1, (z[i][j + 1] - z[i][j+1])); 
glm::vec3 right = glm::vec3(1, 0, (z[i + 1][j] - z[i + 1][j]));

应该是这样的:

//Determination of the normal
glm::vec3 left = glm::vec3(0, 1, (z[i][j + 1] - z[i][j])); 
glm::vec3 right = glm::vec3(1, 0, (z[i + 1][j] - z[i][j]));