OpenGL光照之颜色

颜色

什么是颜色

颜色是通过眼、脑和我们的生活经验所产生的一种对光的视觉效应,我们肉眼所见到的光线,是由频率范围很窄的电磁波产生的,不同频率的电磁波表现为不同的颜色,对色彩的辨认是肉眼受到电磁波辐射能刺激后所引起的一种视觉神经的感觉。

其实在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的(Reflected)颜色。

如何表示物体颜色

首先要知道,在实际模型中物体吸收了其中的大部分颜色,它仅反射了代表物体颜色的部分,被反射颜色的组合就是我们眼睛所感知到的颜色。

具体操作:
把光源的颜色与物体的颜色值相乘,所得到的就是这个物体所反射的颜色(也就是我们所感知到的颜色)

举个例子
光源——白光
物体——蓝色
物体反射颜色——蓝色

glm::vec3 lightColor(1.0f, 1.0f, 1.0f);//白色
glm::vec3 toyColor(0.0f, 1.0f, 0.0f);//蓝色
glm::vec3 result = lightColor * toyColor; // = (0.0f, 1.0f, 0.0f);//蓝色

再举个例子
光源——蓝光
物体——珊瑚红
物体反射颜色——深绿色

glm::vec3 lightColor(0.0f, 1.0f, 0.0f);//蓝色
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);//珊瑚红
glm::vec3 result = lightColor * toyColor; // = (0.0f, 0.5f, 0.0f);//深绿

光照场景的搭建

首先知道需要些什么

  • 光源
  • 物体
  • VAO,VBO

这里建议的做法是将光源与物体的顶点着色器与片段着色器分开来设置,这样容易独自改变而不会受其他因素影响。

光源的顶点着色器:

#version 330 core
layout (location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0);
}

光源的片段着色器:

#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0); //这边光源颜色设置为白色
}

物体的顶点着色器:

#version 330 core
layout (location = 0) in vec3 aPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
	gl_Position = projection * view * model * vec4(aPos, 1.0);
}

物体的片段着色器

#version 330 core
out vec4 FragColor;
  
uniform vec3 objectColor;
uniform vec3 lightColor;

void main()
{
    FragColor = vec4(lightColor * objectColor, 1.0);
}

VAO,VBO
可以让这个灯和其它物体使用同一个VAO,但考虑到接下来会频繁地对顶点数据和属性指针做出修改,我们并不想让这些修改影响到光源(我们只关心光源的顶点位置),因此我们有必要为光源与物体分别创建VAO,由于VBO只是为了储存数据,只需要绑定VBO不用再次设置VBO的数据,这边绘制的都是一样的正方体,VBO可以共用
物体 cubeVAO+VBO

    unsigned int VBO, cubeVAO;
    glGenVertexArrays(1, &cubeVAO);
    glGenBuffers(1, &VBO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glBindVertexArray(cubeVAO);

    // position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

光源 lightCubeVAO+VBO

 	unsigned int lightCubeVAO;
    glGenVertexArrays(1, &lightCubeVAO);
    glBindVertexArray(lightCubeVAO);

    // we only need to bind to the VBO (to link it with glVertexAttribPointer), no need to fill it; the VBO's data already contains all we need (it's already bound, but we do it again for educational purposes)
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//这个可以不要

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

设置渲染循环

		//[...]
 		// render
        // ------
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        
  
        lightingShader.use();
        lightingShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);
        lightingShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
		//物体
        // view/projection transformations
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
        glm::mat4 view = camera.GetViewMatrix();
        lightingShader.setMat4("projection", projection);
        lightingShader.setMat4("view", view);

        // world transformation
        glm::mat4 model = glm::mat4(1.0f);
        lightingShader.setMat4("model", model);

        // render the cube
        glBindVertexArray(cubeVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);

		//光源
        lightCubeShader.use();
        lightCubeShader.setMat4("projection", projection);
        lightCubeShader.setMat4("view", view);
        model = glm::mat4(1.0f);
        model = glm::translate(model, lightPos);//glm::vec3 lightPos(1.2f, 1.0f, 2.0f);
        model = glm::scale(model, glm::vec3(0.2f)); // 这边缩放以表示光源
        lightCubeShader.setMat4("model", model);

        glBindVertexArray(lightCubeVAO);
        glDrawArrays(GL_TRIANGLES, 0, 36);
        //[....]

实现情况:
在这里插入图片描述
灯光为白色, 物体为珊瑚红色。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LV小猪精

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值