简体   繁体   English

OpenGL:如果给定包含总光的叉积,如何渲染单个RGB值?

[英]OpenGL: How do I render individual RGB values given a cross product that contains the total light?

I've been working on my own implementation of a Gouraud style shading model, and I've got the rest of it working pretty much how I want it, but the problem I've run into is it only shows white light. 我一直在自己设计Gouraud样式阴影模型的实现,而其余的工作几乎可以按照我的意愿进行,但是遇到的问题是它仅显示白光。 The calc_color function is where this operation is being performed. calc_color函数是执行此操作的地方。 The Color variable represents the total light of the R, G and B values for that given location. Color变量表示该给定位置的R,G和B值的光线。 I've been assigning Color to all three arrays just to get the shading implemented properly, but now that that is complete, I'd like to figure out a way to extract the R, G and B values from that total light value. 我一直在为所有三个数组分配Color只是为了正确实现阴影,但是现在已经完成了,我想找出一种从总光线值中提取R,G和B值的方法。

I've tried several different things, like taking the total light, and taking a percentage of the Light1r, etc. values but it always ends up looking strange or too bright. 我尝试了几种不同的方法,例如采用总光和采用Light1r的百分比等值,但是它总是看起来奇怪或太亮。

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#ifdef MAC
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

using namespace std;

//Camera variables
int xangle = -270;
int yangle = 0;

//Control Modes (Rotate mode by default)
int mode = 0;
int lightmode = 0;

//Player Position (Y offset so it would not be straddling the grid)
float cubeX = 0;
float cubeY = 0.5;
float cubeZ = 0;

//Vertex arrays for surface
float surfaceX [12][12];
float surfaceY [12][12];
float surfaceZ [12][12];

//Surface Normal arrays
float Nx[11][11];
float Ny[11][11];
float Nz[11][11];

//Color arrays
float R[11][11];
float G[11][11];
float B[11][11];

//Light position and color variables
float Light1x = 0;
float Light1y = 5;
float Light1z = 0;

float Light1r = 0;
float Light1g = 1;
float Light1b = 0;

float Light2x = -5;
float Light2y = 5;
float Light2z = -5;

float Light2r = 0;
float Light2g = 1;
float Light2b = 0;



//Random number generator
float RandomNumber(float Min, float Max)
{
    return ((float(rand()) / float(RAND_MAX)) * (Max - Min)) + Min;
}

//---------------------------------------
// Initialize surface 
//---------------------------------------
void init_surface()
{
    //Initialize X, select column  
    for (int i = 0; i < 12; i++) 
    {
        //Select row
        //Surface is +1 so the far right normal will be generated correctly     
        for (int j = 0; j < 12; j++)
        {   
            //-5 to compensate for negative coordinate values
            surfaceX[i][j] = i-5;
            //Generate random surface height
            surfaceY[i][j] = RandomNumber(5, 7) - 5;
            //surfaceY[i][j] = 0;
            surfaceZ[i][j] = j-5;
        }
    }
}

void define_normals()
{
    //Define surface normals
    for (int i = 0; i < 11; i++)
    {
        for (int j = 0; j < 11; j++)
        {
            //Get two tangent vectors
            float Ix = surfaceX[i+1][j] - surfaceX[i][j];
            float Iy = surfaceY[i+1][j] - surfaceY[i][j];
            float Iz = surfaceZ[i+1][j] - surfaceZ[i][j];
            float Jx = surfaceX[i][j+1] - surfaceX[i][j];
            float Jy = surfaceY[i][j+1] - surfaceY[i][j];
            float Jz = surfaceZ[i][j+1] - surfaceZ[i][j];

            //Do cross product, inverted for upward normals
            Nx[i][j] = - Iy * Jz + Iz * Jy;
            Ny[i][j] = - Iz * Jx + Ix * Jz;
            Nz[i][j] = - Ix * Jy + Iy * Jx;

            //Original vectors
            //Nx[i][j] = Iy * Jz - Iz * Jy;
            //Ny[i][j] = Iz * Jx - Ix * Jz;
            //Nz[i][j] = Ix * Jy - Iy * Jx;

            float length = sqrt( 
                Nx[i][j] * Nx[i][j] + 
                Ny[i][j] * Ny[i][j] + 
                Nz[i][j] * Nz[i][j]);
            if (length > 0)
            {
                Nx[i][j] /= length;
                Ny[j][j] /= length;
                Nz[i][j] /= length;
            }
        }   
    } 
}

void calc_color()
{
    for (int i = 0; i < 10; i++)
    {           
        for (int j = 0; j < 10; j++)
        {
            //Calculate light vector
            //Light position, hardcoded for now 0,1,1
            float Lx = Light1x - surfaceX[i][j]; 
            float Ly = Light1y - surfaceY[i][j];
            float Lz = Light1z - surfaceZ[i][j];

            float length = sqrt(Lx * Lx + Ly * Ly + Lz * Lz);
            if (length > 0)
            {
                Lx /= length;
                Ly /= length;
                Lz /= length;
                        }

            //std::cout << "Lx: " << Lx << std::endl;   
            //std::cout << "Ly: " << Ly << std::endl;
            //std::cout << "Lz: " << Lz << std::endl;



            //Grab surface normals
            //These are Nx,Ny,Nz due to compiler issues
            float Na = Nx[i][j];
            float Nb = Ny[i][j];
            float Nc = Nz[i][j];

            //std::cout << "Na: " << Na << std::endl;   
            //std::cout << "Nb: " << Nb << std::endl;   
            //std::cout << "Nc: " << Nc << std::endl;

            //Do cross product
            float Color = (Na * Lx) + (Nb * Ly) + (Nc * Lz);
            std::cout << "Color: " << Color << std::endl;

            //if (Color > 0)
            //{
            //  Color = Color / 100;
            //}
            //Percent of light color
            //float Ramt = (Light1r/2) / Color;
            //float Gamt = (Light1g/2) / Color;
            //float Bamt = (Light1b/2) / Color;
            //R[i][j] = Ramt * Color;
            //G[i][j] = Gamt * Color;
            //B[i][j] = Bamt * Color;

            R[i][j] = Color;
            G[i][j] = Color;
            B[i][j] = Color;    
        }
    }
}

//---------------------------------------
// Init function for OpenGL
//---------------------------------------
void init()
{
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //Viewing Window Modified
    glOrtho(-7.0, 7.0, -7.0, 7.0, -7.0, 7.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    //Rotates camera
    //glRotatef(30.0, 1.0, 1.0, 1.0);
    glEnable(GL_DEPTH_TEST);

    //Project 3 code
    init_surface();
    define_normals();

    //Shading code
    // glShadeModel(GL_SMOOTH);
    // glEnable(GL_NORMALIZE);

    //X,Y,Z - R,G,B
    // init_light(GL_LIGHT1, Light1x, Light1y, Light1z, Light1r, Light1g, Light1b);
    // init_light(GL_LIGHT2, Light2x, Light2y, Light2z, Light2r, Light2g, Light2b);
    //init_light(GL_LIGHT2, 0, 1, 0, 0.5, 0.5, 0.5);


}

void keyboard(unsigned char key, int x, int y)
{

///TODO: allow user to change color of light

    //Controls
    //Toggle Mode  
    if (key == 'q')
    {
        if(mode == 0)
        {       
            mode = 1;
            std::cout << "Switched to Light mode (" << mode << ")" << std::endl;    
        }
        else if(mode == 1)
        {   
            mode = 0;
            std::cout << "Switched to Rotate mode (" << mode << ")" << std::endl;
        }
    }
    //Toggle light control
    else if (key == 'e' && mode == 1)
    {
        if(lightmode == 0)
        {       
            lightmode = 1;
            std::cout << "Switched to controlling light 2 (" << lightmode << ")" << std::endl;  
        }

        else if(lightmode == 1)
        {       
            lightmode = 0;
            std::cout << "Switched to controlling light 1 (" << lightmode << ")" << std::endl;  
        }
    }

    ////Rotate Camera (mode 0)
    //Up & Down
    else if (key == 's' && mode == 0)
        xangle += 5;
    else if (key == 'w' && mode == 0)
    xangle -= 5;

    //Left & Right
    else if (key == 'a' && mode == 0) 
    yangle -= 5;
    else if (key == 'd' && mode == 0) 
    yangle += 5;

    ////Move Light (mode 1)
    //Forward & Back
    else if (key == 'w' && mode == 1) 
    {
        if (lightmode == 0) 
        {       
            Light1z = Light1z - 1;
            //init_surface();           
            //define_normals();         
            //calc_color();
            //glutPostRedisplay();

        }
        else if (lightmode == 1)
        Light2z = Light2z - 1;
        //init_surface();

    }

    else if (key == 's' && mode == 1)
    {
        if (lightmode == 0)
        Light1z = Light1z + 1;

        else if (lightmode == 1)
        Light2z = Light2z + 1;
    }

    //Strafe
    else if (key == 'd' && mode == 1)
    {
        if (lightmode == 0)
        Light1x = Light1x + 1;

        else if (lightmode == 1)
        Light2x = Light2x + 1;  
    }
    else if (key == 'a' && mode == 1)
    {
        if (lightmode == 0)     
        Light1x = Light1x - 1;
        else if (lightmode == 1)
        Light2x = Light2x - 1;

    }   

    //Up & Down (Cube offset by +0.5 in Y)
    else if (key == 'z' && mode == 1)
    {
        if (lightmode == 0)
        Light1y = Light1y + 1;
        else if (lightmode == 1)
        Light2y = Light2y + 1;
    }
    else if (key == 'x' && mode == 1)
    {
        if (lightmode == 0)
        Light1y = Light1y - 1;
        else if (lightmode == 1)
        Light2y = Light2y - 1;
    }

    //Redraw objects
    glutPostRedisplay();
}


//---------------------------------------
// Display callback for OpenGL
//---------------------------------------
void display()
{       
        // Clear the screen
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //Rotation Code
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRotatef(xangle, 1.0, 0.0, 0.0);
    glRotatef(yangle, 0.0, 1.0, 0.0);

    //Light Code
    // init_material(Ka, Kd, Ks, 100 * Kp, 0.8, 0.6, 0.4);  

    // init_light(GL_LIGHT1, Light1x, Light1y, Light1z, Light1r, Light1g, Light1b);
        // init_light(GL_LIGHT2, Light2x, Light2y, Light2z, Light2r, Light2g, Light2b);

    // glEnable(GL_LIGHTING);
    //Color Code
    calc_color();

    //Draw the squares, select column  
    for (int i = 0; i <= 9; i++)
    {
        //Select row        
        for (int j = 0; j <= 9; j++)
        {   
            glBegin(GL_POLYGON); 

            //Surface starts at top left
            //Counter clockwise

            glColor3f(R[i][j], G[i][j], B[i][j]);
            std::cout << R[i][j] << " " <<  G[i][j] << " " <<  B[i][j] << endl;
            // glNormal3f(Nx[i][j], Ny[i][j], Nz[i][j]);
            glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);

            glColor3f(R[i][j+1], G[i][j+1], B[i][j+1]);
            // glNormal3f(Nx[i][j+1], Ny[i][j+1], Nz[i][j+1]);
            glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);

            glColor3f(R[i+1][j+1], G[i+1][j+1], B[i+1][j+1]);
            // glNormal3f(Nx[i+1][j+1], Ny[i+1][j+1], Nz[i+1][j+1]);
            glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);

            glColor3f(R[i+1][j], G[i+1][j], B[i+1][j]);
            // glNormal3f(Nx[i+1][j], Ny[i+1][j], Nz[i+1][j]);
            glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);

            glEnd();
        }
    }

    // glDisable(GL_LIGHTING);
    //Draw the normals
    for (int i = 0; i <= 10; i++)
    {
        for (int j = 0; j <= 10; j++)
        {

            glBegin(GL_LINES);
            glColor3f(0.0, 1.0, 1.0);
            float length = 1;
            glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);
                glVertex3f(surfaceX[i][j]+length*Nx[i][j], 
                surfaceY[i][j]+length*Ny[i][j], 
                surfaceZ[i][j]+length*Nz[i][j]);
            glEnd();
        }
    }

    //Marking location of lights
    glPointSize(10);
    glBegin(GL_POINTS);
    glColor3f(Light1r, Light1g, Light1b);
    glVertex3f(Light1x, Light1y, Light1z);      
    glEnd();

    glPointSize(10);
    glBegin(GL_POINTS);
    glColor3f(Light2r, Light2g, Light2b);
    glVertex3f(Light2x, Light2y, Light2z);      
    glEnd();

    //+Z = Moving TOWARD camera in opengl
    //Origin point for reference
    glPointSize(10);
    glColor3f(1.0, 1.0, 0.0);
    glBegin(GL_POINTS);
    glVertex3f(0, 0, 0);        
    glEnd();

    //Assign Color of Lines
    float R = 1;
    float G = 1;
    float B = 1;
    glBegin(GL_LINES);
    glColor3f(R, G, B);

    ////Drawing the grid
    //Vertical lines
    for (int i = 0; i < 11; i++)
    {
        int b = -5 + i;

        glVertex3f(b, 0, -5);
        glVertex3f(b, 0, 5);
    }

    //Horizontal lines
    for (int i = 0; i < 11; i++)
    {
        int b = -5 + i;
        glVertex3f(-5,0,b);
        glVertex3f(5,0,b);

    }

    glEnd();
    glFlush();  
}

//---------------------------------------
// Main program
//---------------------------------------
int main(int argc, char *argv[])
{
    srand(time(NULL));

    //Print Instructions
    std::cout << "Project 3 Controls: " << std::endl;
    std::cout << "q switches control mode" << std::endl;
    std::cout << "w,a,s,d for camera rotation" << std::endl;


    //Required
    glutInit(&argc, argv);
    //Window will default to a different size without
    glutInitWindowSize(500, 500);
    //Window will default to a different position without
    glutInitWindowPosition(250, 250);
    //
    glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
    //Required
    glutCreateWindow("Project 3");
    //Required, calls display function
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);

    //Required
    init();
    glutMainLoop();



   return 0;
}

I recommend to write your first Shader program , which does per fragment lighting and consists of a Vertex Shader and a Fragment Shader . 我建议编写您的第一个Shader程序 ,该程序对每个片段进行照明,并由Vertex ShaderFragment Shader组成
The program has to use GLSL version 2.00 ( OpenGL Shading Language 1.20 Specification ). 该程序必须使用GLSL版本2.00( OpenGL阴影语言1.20规范 )。 This program can access the Fixed function attributes by the built in variables gl_Vertex , gl_Normal and gl_Color , as the fixed function matrices gl_NormalMatrix , gl_ModelViewMatrix and gl_ModelViewProjectionMatrix and the function ftransform() . 该程序可访问固定功能由内置在变量属性gl_Vertexgl_Normalgl_Color ,作为固定功能矩阵gl_NormalMatrixgl_ModelViewMatrixgl_ModelViewProjectionMatrix和功能ftransform()
See als Built in Vertex Attributes and Hello World in GLSL . 请参见内置于Vertex属性中的 als和GLSL中的Hello World
Further the program has to use Uniform Variables for the light colors and positions. 此外,程序必须对灯光的颜色和位置使用统一变量

The Vertex shader transforms the model space coordinates and vectors to view space and pass the to the fragment shader by Varying Variables : 顶点着色器将模型空间的坐标和向量转换为视图空间,并通过Varying Variables将其传递给片段着色器:

std::string vertex_shader = R"(
#version 120

uniform vec3 u_light_pos_1;
uniform vec3 u_light_pos_2;

varying vec3 v_pos;
varying vec3 v_nv;
varying vec4 v_color;
varying vec3 v_light_pos1;
varying vec3 v_light_pos2;

void main()
{
    v_pos        = (gl_ModelViewMatrix * gl_Vertex).xyz;
    v_nv         = gl_NormalMatrix * gl_Normal;
    v_color      = gl_Color;
    v_light_pos1 = (gl_ModelViewMatrix * vec4(u_light_pos_1, 1.0)).xyz;
    v_light_pos2 = (gl_ModelViewMatrix * vec4(u_light_pos_2, 1.0)).xyz;
    gl_Position  = ftransform();
}
)";

The fragment shader dose the per Fragment Light calculations in view space: 片段着色器按视图空间中的每个“片段光”计算进行分配:

std::string fragment_shader = R"(
#version 120

varying vec3 v_pos;
varying vec3 v_nv;
varying vec4 v_color;
varying vec3 v_light_pos1;
varying vec3 v_light_pos2;

uniform vec3 u_light_col_1;
uniform vec3 u_light_col_2;

void main()
{
    vec3 N  = normalize(v_nv); 
    vec3 L1 = normalize(v_light_pos1 - v_pos);
    vec3 L2 = normalize(v_light_pos2 - v_pos);

    float kd_1 = max(0.0, dot(L1, N));
    float kd_2 = max(0.0, dot(L2, N));

    vec3 light_sum = kd_1 * u_light_col_1 + kd_2 * u_light_col_2;

    gl_FragColor = vec4(v_color.rgb * light_sum, v_color.a);
}
)";

Compile the shader stages 编译着色器阶段

GLuint generate_shader(GLenum stage, const std::string &source)
{
    GLuint shader_obj = glCreateShader(stage);
    const char *srcCodePtr = source.c_str();
    glShaderSource(shader_obj, 1, &srcCodePtr, nullptr);
    glCompileShader(shader_obj);
    GLint status;
    glGetShaderiv(shader_obj, GL_COMPILE_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint maxLen;
        glGetShaderiv(shader_obj, GL_INFO_LOG_LENGTH, &maxLen);
        std::vector< char >log( maxLen );
        GLsizei len;
        glGetShaderInfoLog(shader_obj, maxLen, &len, log.data());
        std::cout << "compile error:" << std::endl << log.data() << std::endl;
    }
    return shader_obj;
}

and link the program. 并链接程序。

GLuint generate_program(const std::string &vert_sh, const std::string &frag_sh)
{
    std::cout << "compile vertex shader" << std::endl;
    GLuint vert_obj = generate_shader(GL_VERTEX_SHADER, vert_sh);
    std::cout << "compile fragment shader" << std::endl;
    GLuint frag_obj = generate_shader(GL_FRAGMENT_SHADER, frag_sh);

    std::cout << "link shader program" << std::endl;
    GLuint program_obj = glCreateProgram();
    glAttachShader(program_obj, vert_obj);
    glAttachShader(program_obj, frag_obj);
    glLinkProgram(program_obj);
    GLint status;
    glGetProgramiv(program_obj, GL_LINK_STATUS, &status);
    if (status == GL_FALSE)
    {
        GLint maxLen;
        glGetProgramiv(program_obj, GL_INFO_LOG_LENGTH, &maxLen);
        std::vector< char >log( maxLen );
        GLsizei len;
        glGetProgramInfoLog(program_obj, maxLen, &len, log.data());
        std::cout  << "link error:" << std::endl << log.data() << std::endl;
    }

    glDeleteShader(vert_obj);
    glDeleteShader(frag_obj);
    return program_obj;
}

Further get the uniform locations by glGetUniformLocation in the function init : 通过函数init glGetUniformLocation进一步获取统一位置:

GLuint diffuse_prog_obj = 0;
GLint loc_l_pos[] = {-1, -1};
GLint loc_l_col[] = {-1, -1};
void init()
{
    diffuse_prog_obj = generate_program(vertex_shader, fragment_shader);
    loc_l_pos[0] = glGetUniformLocation(diffuse_prog_obj, "u_light_pos_1");
    loc_l_pos[1] = glGetUniformLocation(diffuse_prog_obj, "u_light_pos_2");
    loc_l_col[0] = glGetUniformLocation(diffuse_prog_obj, "u_light_col_1");
    loc_l_col[1] = glGetUniformLocation(diffuse_prog_obj, "u_light_col_2");

    // [...]
}

The shader program can be used by glUseProgram . 可以通过glUseProgram使用着色器程序。 The uniforms are set by glUniform * . 制服由glUniform *设置。
Beside the vertex coordinates, the normal vector attributes have to be set per vertex, to make the light calculations proper work. 除了顶点坐标外,还必须为每个顶点设置法线向量属性,以使光照计算正常工作。 But it is sufficient to set a single color for the entire mesh: 但是为整个网格设置单一颜色就足够了:

void display()
{
    // [...]

    // install program
    glUseProgram(diffuse_prog_obj);

    // set light positions and colors 
    glUniform3f(loc_l_pos[0], Light1x, Light1y, Light1z);
    glUniform3f(loc_l_pos[1], Light2x, Light2y, Light2z);
    glUniform3f(loc_l_col[0], Light1r, Light1g, Light1b);
    glUniform3f(loc_l_col[1], Light2r, Light2g, Light2b);

    // set object color
    glColor3f(1, 1, 0.5);

    //Draw the squares, select column  
    for (int i = 0; i <= 9; i++)
    {
        //Select row        
        for (int j = 0; j <= 9; j++)
        {   
            glBegin(GL_POLYGON); 

            std::cout << R[i][j] << " " <<  G[i][j] << " " <<  B[i][j] << endl;
            glNormal3f(Nx[i][j], Ny[i][j], Nz[i][j]);
            glVertex3f(surfaceX[i][j], surfaceY[i][j], surfaceZ[i][j]);

            glNormal3f(Nx[i][j+1], Ny[i][j+1], Nz[i][j+1]);
            glVertex3f(surfaceX[i][j+1], surfaceY[i][j+1], surfaceZ[i][j+1]);

            glNormal3f(Nx[i+1][j+1], Ny[i+1][j+1], Nz[i+1][j+1]);
            glVertex3f(surfaceX[i+1][j+1], surfaceY[i+1][j+1], surfaceZ[i+1][j+1]);

            glNormal3f(Nx[i+1][j], Ny[i+1][j], Nz[i+1][j]);
            glVertex3f(surfaceX[i+1][j], surfaceY[i+1][j], surfaceZ[i+1][j]);

            glEnd();
        }
    }

    // invalidate installed program
    glUseProgram(0);

    // [...]
}

See the preview of you program, with the applied suggestions: 请参阅您的程序预览,并提供以下建议:

A common formula to calculate aa diffuse light is to calculate the Dot product of the normal vector of the surface and the vector to from the surface to the light source. 计算漫射光的常用公式是计算表面法线矢量与从表面到光源的矢量的点积 See How does this faking the light work on aerotwist? 请参阅此伪造的灯光如何在气旋上工作? .

kd = max(0, L dot N)

To get the color of the light, the RGB values are component wise multiplied by the diffuse coefficient: 为了获得光的颜色,将RGB值逐分量乘以漫射系数:

(Cr, Cg, Cb) = (LCr, LCg, LCb) * kd

If there are multiple light sources, then the light colors are summed: 如果有多个光源,则将灯光颜色相加:

(Cr, Cg, Cb) = (LC1r, LC1g, LC1b) * max(0, L1 dot N) + (LC2r, LC2g, LC2b) * max(0, L2 dot N)

Note, if the surface (material) has an additional color, then ths color would have to be component wise multiplied to the final color: 请注意,如果表面(材料)具有其他颜色,则必须按分量将颜色乘以最终颜色:

(Cr, Cg, Cb) = (Cr, Cg, Cb) * (CMr, CMg, CMb)

Write a function which calculates the light for 1 single light source and add the light to the final color: 编写一个计算单个光源的光并将其添加到最终颜色的函数:

void add_light_color(int i, int j, float lpx, float lpy, float lpz, float lcr, float lcg, float lcb)
{
    float Lx = lpx - surfaceX[i][j]; 
    float Ly = lpy - surfaceY[i][j];
    float Lz = lpz - surfaceZ[i][j];

    float length = sqrt(Lx * Lx + Ly * Ly + Lz * Lz);
    if (length <= 0.0)
        return;

    float kd = Lx/length * Nx[i][j] + Ly/length * Ny[i][j] + Ly/length * Ny[i][j];
    if ( kd <= 0.0 )
    return; 

    R[i][j] += kd * lcr;
    G[i][j] += kd * lcg;
    B[i][j] += kd * lcb;
}

Traverse the filed of attributes, set each color (0, 0, 0) and use the above function to add the color form each light source: 遍历属性字段,设置每种颜色(0、0、0),然后使用上述功能从每种光源添加颜色:

void calc_color()
{
    float lp1[] = {Light1x, Light1y, Light1z};
    float lp2[] = {Light2x, Light2y, Light2z};
    float lc1[] = {Light1r, Light1g, Light1b};
    float lc2[] = {Light2r, Light2g, Light2b};

    for (int i = 0; i < 10; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            R[i][j] = G[i][j] = B[i][j] = 0.0;  

            add_light_color(i, j, Light1x, Light1y, Light1z, Light1r, Light1g, Light1b);
            add_light_color(i, j, Light2x, Light2y, Light2z, Light2r, Light2g, Light2b);
        }
    }
}

The result for the following light color settings: 以下浅色设置的结果:

float Light1r = 1;
float Light1g = 0;
float Light1b = 0;

float Light2r = 0;
float Light2g = 1;
float Light2b = 0;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM