GVKun编程网logo

[computer graphics] 简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理(phong光照明模型公式)

2

如果您想了解[computergraphics]简单光照模型(Phong和Blinn-Phong)和明暗处理和phong光照明模型公式的知识,那么本篇文章将是您的不二之选。我们将深入剖析[comput

如果您想了解[computer graphics] 简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理phong光照明模型公式的知识,那么本篇文章将是您的不二之选。我们将深入剖析[computer graphics] 简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理的各个方面,并为您解答phong光照明模型公式的疑在这篇文章中,我们将为您介绍[computer graphics] 简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理的相关知识,同时也会详细的解释phong光照明模型公式的运用方法,并给出实际的案例分析,希望能帮助到您!

本文目录一览:

[computer graphics] 简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理(phong光照明模型公式)

[computer graphics] 简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理(phong光照明模型公式)

简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理

支持点光源和平行光,是一种简单光照模型,它将光照分解成了三个部分,分别为

  • 漫反射
  • 镜面反射
  • 环境光

如图所示,是一个简单的几何模型。

  • L 是光源方向
  • N 是法线方向
  • R 是反射方向
  • V 是视线方向
  • H L V 的平分
  • 所有向量都是单位向量

理想漫反射

当光源来自一个方向时,漫反射均匀地向各个方向传播,与视点无关,是由物体表面粗糙不平引起的,漫反射的空间分布是均匀的,也就是说不论从哪个方向看去,同一个点的漫反射光强都是一样的。物体上的点 P,法向量为 N,入射光强度为 IpL P 指向光源的方向。如果所有所有的向量都是单位向量,那么有

Id=IpKd(LN)

其中 Kd=(Kdr,Kdg,Kdb) 这三个分量分别是 RGB 三原色的漫反射系数,可以反应物体的颜色。同样的 Ip=(Ir,Ig,Ib) 可以通过分量来设置光源的颜色。

镜面反射

对于理想镜面,反射光集中在一个方向,并遵守反射定律。对于一般的光滑表面,反射光则集中在一个范围内,且反射定律决定的方向光强最大。所以从不同位置观察到的镜面反射光强不同。镜面反射光可表示为

Is=IpKs(RV)n

RV 计算的是反射方向和视线方向的夹角,夹角越小,强度越大。n 是反射指数,反应了物体的表面的光滑程度,一般 1-2000。n 越大约光滑,因为 n 越大,例如 2000,那么当夹角很小时,例如很接近 1,如 0.9,但是经过 2000 乘方,就变得很小了,这意味着只有无限接近反射方向,才能看到高光,其他方向不行,这就表示物体很光滑。反过来,n 很小那么移动一点角度,也能看到衰弱的高光,所以光斑会比较明显。

在镜面反射模型中,最终要的是计算 R 的方向,R 可以通过入射方向和法线方向计算出来

因为这里的向量都是单位向量,只有方向不一致

||L||cosθ=||M||=cosθMNR=L+2M=2NcosθL=2N(NL)L

高光区域只反映光源的颜色,漫反射才能设定物体的颜色。

环境光

光源间接对物体施加的明暗影响,在物体和环境之间多次反射。在简单光照模型中进行了简化,通常用一个常数来模拟环境光

I=IaKa

Ia 是环境光强,Ka 为物体对环境光的反射系数。

Phong 模型

I=IaKa+IpKd(LN)+IpKs(RV)n

Phong 模型是上述三种因素的叠加,其中 R 的计算比较费时,需要对每一点计算一次 R 的值。

Blinn-Phong 模型

由于 Phong 模型计算较为耗时,后来提出了一种对 Phong 模型的修改,Blinn-Phong 模型。
假设:

  1. 光源在无穷远处,光线的方向 L 为常数(这就意味着,对物体上所有点来说,光线的方向都是一致的,正常情况应该是光源到点的向量,每个点的光照方向都不一致)
  2. 视点在无穷远处,视线的防线 V 为常数(这个同理)
  3. 此模型针对高光部分进行了修改,RV 的计算用 HN 近似,其中 H=(L+V)/||L+V||,也就是 L V 的平分向量。当 V 接近 R 的时候,H 也接近 N,符号高光的规律。对于所有点,H 只需计算一次。

所以 Blinn-Phong 模型的可以表示成:

I=IaKa+IpKd(LN)+IpKs(HN)n

(图片中应该采用了明暗处理,不仅是光照模型)

明暗处理

如今的物体大多数用多边形表示,一个多边形的法线方向一致,因此一个多边形内部的像素相同,而在邻接出可能会有突变,感觉不连续。为了让过度平滑,基本思想是:对多边形的顶点计算合适的光强度,在内部进行均匀插值。其中有两种主要的做法:

  • 计算物体表面多边形顶点的光强,然后插值,求多边形内部光强。
  • 对内部点的法向量进行插值,而顶点的法向量用相邻多边形的法向量的平均值得到。

Gouraud 明暗处理(双线性光强插值)

基本算法

  1. 计算多边形顶点的平均法向量
  2. 用 Phong 模型计算顶点的平均强度
  3. 插值计算离散边上的各点光强
  4. 插值计算多边形区域内的各点光强

计算速度比简单光照模型有了很大的提高,解决了颜色突变问题,但是镜面反射效果不理想。

Phong 明暗处理(双线性法向量插值)

和 Gouraud 方法基本类似,只不过是对法向量插值。多边形顶点的法向量用相邻多边形的法向量的平均值。而内部每个点都要计算法向量,用顶点的法向量插值得到。
这种做法效果好,可以产生正确的高光,但是计算量很大。

  • [1] 维基百科
  • [2] 计算机图形学基础教程 胡事民

6GEN715 – Computer Graphics

6GEN715 – Computer Graphics

December 18, 2017 [6GEN715 PROJECT INSTRUCTIONS]

6GEN715 – Computer Graphics
Project Instructions
Dr. Yawei Liang at RMC
2017-12
o The project is worth 20% of your final mark of this course.
o The final report is to be completed by Dec. 29, 2017. A project mark of zero will be assigned
if you submit anything late.
o Project presentations are to be during the last but one day of teaching.

  1. Overview
    Objective: In a group of not more than 4 students, you have to use OpenGL to create a virtual
    home on a piece of land, such as:

And there is at least one tree beside your dream home and your program should enable to view
the virtual environment from different viewpoints.
December 18, 2017 [6GEN715 PROJECT INSTRUCTIONS]
Dr. Yawei Liang, RMCC Page 2
Three steps are designed to fulfil this project:

  1. Group not more than 4 students as a team.
  2. Design and build your model and implement the model, test; and give a demo to the class
    at the end of 2nd week teaching.
  3. Write a report on your project and explain what OpenGL techniques you use, and what
    you would like to learn more to make your home better displayed.
    A minimum project could be an idea of using some Computer Graphics (CG) technique(s) to
    create a virtual environment. A better project could include the idea and a suggestion of an
    implementation choosing from many others possible implementations. A desired project should
    not only discuss the idea and the implementation, but also have an attempted implementation and
    analysis of your results.
  4. Demo Days - 10 Marks
    May 16 will be the Demo Day; you should be prepared to demonstrate your working project to
    our class.
    You will get up to 10 marks (2 each) for the following categories:
    (H) house - A house should be created and displayed.
    (T) tree- At least one tree should be created and displayed.
    (S) Sun – the sun is a must object.
    (E) extra environment object(s) - you can create any other extra object on the piece of
    land you have.
    (V) viewpoints - your program should enable viewer to view your home with different
    angles.
    All presentations must be in Visual C++ with OpenGL with or without GLSL. Upload your
    whole project into a specified folder in the teacher’s computer within the lab before you present
    your project.
  5. Final Report - 10 Marks
    You are expected to write a final report in Word format based on your experience. You should
    describe what you planned to do, what had been done, why it was worthwhile, and provided a
    good learning experience.
    The total length of your report should be no more than 1500 words. Include any tables, diagrams
    and algorithm(s) needed to illustrate your work. Shorter is OK, as long as you feel you''ve said
    what needs to be said. Your report should have five sections and an appendix, as described below:
    December 18, 2017 [6GEN715 PROJECT INSTRUCTIONS]
    Dr. Yawei Liang, RMCC Page 3
  6. Cover Page. With the Grading Form (attached in the same folder of this file), followed by
    your name and student number.
  7. Introduction and Motivation. Discuss what the problem you''re dealing with in this project is;
    how you would solve it.
  8. Design and Implementations. Describe how your solution works, the major steps of your
    implementation of the proposed solution. Do include some screenshots of your final demo into
    your report.
  9. Shortcomings. Describe any known errors or omissions in your implementation. Like all
    scientific work, it is your duty to be honest. You will not have marks deducted for honesty.
  10. Conclusions. Summarize your project in a few words, and say what you would do differently
    if you were going to do it all over again.
  11. Appendix. You should include any special instructions (e.g. how to install and run your
    program).
    The report will be marked out of 10 marks, with 2 marks each for:
    (C) clarity - Does your report explain everything that you did?
    (D) design - Did you design your implementation well? Did you use any CG technique(s)
    where appropriate?
    (E) English - Are there any spelling or grammatical errors? Is your writing clear and
    succinct?
    (N) neatness - Are the text, code and figures laid out well? Is your writing/printing legible?
    (T) thoroughness - Is the report complete? Did you leave important things out? Did you
    forget to describe important cases, rules, or program behaviour? Did you make errors in
    your project that aren''t listed in the shortcomings?
    The deadline for submitting the report is on Dec. 29, 2017. This report must be uploaded into the
    same folder of your project in the teacher’s computer within the lab.
    WX:codehelp

A Self-Organized Computer Virus Demo in C

A Self-Organized Computer Virus Demo in C

A Program that can modify herself and copy herself to somewhere else and execute it. Just like gene-transformable virus.

Here''s the sample code.

#include "stdio.h"
#include "windows.h"

#define MAX_LOOP 10000

int main(int argc, const char** argv)
{
	/*** THE VIRUS LOGIC PART ***/
	//GENE_MARK
	int a = 0;

	printf("GENE PRINT:%d\n", a);
	/*** THE VIRUS LOGIC PART ***/


	// FILE NAME
	char file_name[30] = "test";

	// MAKE A COPY OF HERSELF
	FILE* source = fopen("test.c""r");
	FILE* descendant = fopen("descendant.c""w+");
	
	printf("SOURCE FILE OPEN RESULT IS : %d \n", (int)source);
	printf("DESCENDANT FILE CREATED: %d \n", (int)descendant);
	
	if(descendant==NULL)
	{
		printf("ERROR ON CREATING DESCENDANT.\n");
		return -1;
	}
	char buff[100] = {0};
	// REPLACE GENE MARK PROGRAM
	char letter = 0;
	
	// GENE LINE
	int idx = 0;
	int loop = 0;
	
	int buff_idx = 0;
	
	while(!feof(source))
	{
		// ALARM
		if(loop>MAX_LOOP)
			break;
		
		loop ++;
		
		fread(&letter, sizeof(char), 1, source);
		
		buff[buff_idx] = letter;
		buff_idx ++;
		
		if(letter==''\n'')
		{
			if(idx==9)
			{
				// TRANSFORM GENE
				memset(buff, 0100);
				buff_idx = 0;
				strcat(buff, "int a = 1;\n");
			}
			fwrite(buff, sizeof(char), strlen(buff), descendant);
			// CLEAR BUFFER
			memset(buff, 0100);
			buff_idx = 0;
			idx ++;
		}
	}
	
	// DEAL WITH LEFT LETTERS IN BUFFER
	if(strlen(buff)>0)
	{
		strcat(buff, "\n");
		fwrite(buff, sizeof(char), strlen(buff)+1, descendant);
	}
	
	// CLOSE ALL FILES
	fclose(source);
	fclose(descendant);
	
	// until the descendant file is written over
	
	/*** COMPILE HERSELF ***/
	char* source_file = "descendant.c";
	char* dest_file = "descendant.exe";
	char command[100] = {0}; 
	strcat(command, "gcc -o ");
	strcat(command, dest_file);
	strcat(command, " ");
	strcat(command, source_file);
	// COMPILATION
	system(command);
	/***********************/
	
	
	printf("COPYING MYSELF DONE.\n");
	
	printf("WAITING FOR NEXT INSTRUCTION...\n");
	char cmd = getchar();
	if(cmd==''Y'')
	{
		printf("BEGIN EXECUTE THE COPYFILE EXECUTION...\n");
//GENE_MARK	
		system("descendant.exe");
		printf("EXECUTION PROCESS IS ACTIVATED, TASK DONE. EXIT SYSTEM.");
	}
	else
		printf("YOU CHOOSE TO EXIT SYSTEM. BYE!");

	return 0;
}

If you have any suggestions or ideas, please feel free comment below, thanks!

Blinn-phong model importance sampling

Blinn-phong model importance sampling

本文仅讨论 Blinn-phong BRDF model 的高光specular部分,其BRDF 表达式为:

请输入图片描述

H 是半角向量:

请输入图片描述

普通的monte carlo 方法在对BRDF 进行采样的时候是对出射光方向采样(比如phong模型),但是这里对光照结果产生影响的是半角向量,因此我们对半角向量H采样,然后再反推出出射光的方向。

山寨一张GPU gem 的图:

请输入图片描述

我们用θ ø 表示在 以N轴为Z轴的空间里H 向量的方向(球坐标), 这样只要θ按照余弦n次方的分布采样就能做到和BRDF一致实现重要性采样了;具体:

请输入图片描述

这样采样之后半角的分布就是:

请输入图片描述

β 就是半角和法向量的夹角。

之后转换为x y z 坐标:

请输入图片描述

然后就是采样出来的H向量了,需要注意的是这里我们生产的分布是H向量的,在实际计算辐射积分的时候是关于入射向量的,所以需要做一个分布的转换(参考PBRT章节13.5)

请输入图片描述

这样我们可以得出 最终采样的pdf表达式为:

请输入图片描述

蒙特卡洛的估计量(BRDF / PDF) 可以简化成:

请输入图片描述

放一张path tracing 的结果:

请输入图片描述

Blinn-Phong反射模型

Blinn-Phong反射模型

前言
在这一章中,实现光线与对象表面之间的相互作用。目的是在渲染流水线中增加着色功能,所以这里只讨论最基础的局部光照模型。与全局光照不同,在局部光照模型中,着色点的颜色值只取决于着色点表面的材质属性、表面的局部几何性质以及光源的位置与属性,而与场景中其他的表面无关。

渲染流程与场景定义
因为不考虑全局光照,只考虑从光源发出的光线,具体来说只考虑光源和表面之间的一次单独的相互作用。所以这个问题可分解为两个独立的部分:

定义场景中的光源(这里只介绍点光源)
定义一个描述材质和光线之间相互作用的反射模型(phong与Blinn-Phong反射模型)。
首先从一个点光源发出的光线中,由于观察者只看到从光源出发后最终到达他眼睛的那些光线。也就是说可以分两种情况:

要么这条光线从光源出发后直接进入观察者的眼睛,这时候看到的就是光源的颜色。
要么这条光线经过一条复杂的路线并且与场景中的对象发生多次相互作用(这里只考虑一次),之后进入观察者的眼睛,这时候看到的是光源与表面材质之间的相互作用。
image.png

在webgl中,经常使用投影平面来代替观察者。从概念上来讲,投影平面上位于裁剪窗口内的部分被映射到显示器上,因此可以把投影平面用直线分割成许多小的矩形,每一个小矩形都对屏幕上的一个像素。也就是说光源和对象表面的颜色决定了一个或多个像素的颜色。

反射光类型
学过初中物理就知道,基本上分为3种不同的反射光类型。

环境光:它的特点是使场景获得均匀的照明,是光线与场景对象的多次相互作用的结果。这里简单的设置为一个常数来模拟。
漫反射光:它的特点是把入射光线向各个方向散射,而且向各个方向散射的光线的强度都相等,因此不同位置的观察者看到的反射光线都是一样的。
镜面反射光:它的特点是看起来有光泽,因为被反射出去的大多数光线的方向都是和反射角的方向很接近。反射光线的方向服从入射角等于反射角这一规律。
为了简单起见,下面说的光照是建立一个点上,这个点就是着色点。而且这个点应该是在物体的表面,所以这点的光照就是光源对这点的着色效果。
image.png
如图所示,首先来定义一些单位向量:

着色点的法线n
光照方向l
摄像机观测方向v
物体表面的一些参数
光的传播与能量守恒
光在传播过程中是会有衰减的。

image.png

比如说一开始光集中在一个单位球上,也就是最里面的球,此时球上每个点的接收到的能量就是光的能量除以球的面积。

当光传播到半径为r的球上时,也就是最外面的球时。根据能量守恒定律,最外面的球上每个点所接收到的能量要比小,根据公式可得物体表面接收到的能量是与光传播的距离平方成反比。

也就是说要计算着色点所接收到光的能量,就要计算光到着色点的距离。

Phong反射模型
该反射模型是由Phong首先提出的。实践上不但计算效率高而且模拟现实的效果非常好,以至于对各种各样的光照条件和材质属性都获得很好渲染效果。

Phong反射模型考虑了上述说明的三种相互作用:环境光、漫反射和镜面反射。对每个颜色分量来说,都有独立的环境光分量、漫反射光分量和镜面反射光分量。最后将这三个分量加起来组成最后的颜色。

使用4个向量来计算着色点p的颜色值。其中未知的是反射向量r,而r可以由n和l确定的

image.png

环境光反射
在表面上所有点的环境光强度LaL_{a}La​都是相同的。环境光的一部分被表面吸收,还有一部分被表面反射,被反射的部分的强度由环境光反射系统kak_{a}ka​,所以此时RaR_{a}Ra​=kak_{a}ka​。其中0 <= kak_{a}ka​ <= 1。

所以IaI_{a}Ia​ = kak_{a}ka​ * LaL_{a}La​

代码实现
在代码中,添加环境光非常的简单,只需设置一个很小的常量将其乘上物体颜色即可

void main () {

vec3 ambient = 0.05 * color;

}
复制代码
漫反射
当一束平行的入射光线射到粗糙的表面时,表面会把光线向着四面八方反射。
image.png
可以看到平面法线与光照方向有一定的夹角,而且根据这个夹角的不同着色点得到的明暗是不一样的。

image.png

假如每根光线的能量是均等的。分析左边的图,可以看到当物体表面与光照方向是垂直的话,会接收到所有的6根光线。而中间图则是旋转了这个物体到一定的角度,只能接收到3根光线,按理说这个物体表面应该是比左边要暗的。

所以着色点的明亮程度与光照方向l和物体表面法线n的夹角是有关系的。而在现实中也能观察到,比如说地球的四季温度的不同,就是光照方向与地表法线的角度有关。

这个关系就是著名的Lamber''s consine law定律:光照方向与表面法线方向的余弦是成正比的:

cosθ=l∗ncosθ = l * ncosθ=l∗n

所以漫反射又称为Lambertian Shading:

首先定义光的强度I,当光到达物体表面时的能量就是I/r2I / r^2I/r2。光被吸收多少就是根据夹角余弦来计算,这个余弦根据光照向量与法线向量的点乘计算得出。

Ld=kd(I/r2)max(0,n∗l)L_d = k_d(I / r^2)max(0, n * l)Ld​=kd​(I/r2)max(0,n∗l)

至于max(0, n * l)的意思是,排除余弦是负数的情况。因为在现实生活中(表面不透明的情况下),光是不可能从负角度来照亮物体的表面。出现这种情况,就赋值0.

至于k,它是一个吸收系数。它表示这物体表面吸收了多少光,反射多少光。当kd=1k_d=1kd​=1时,也就是说物体表面完全不吸收光,全部反射出去。
image.png
代码实现
在代码中,法向量是已知的

const aNormal = gl.getAttribLocation(program, ''aNormal'');
gl.vertexAttribPointer(aNormal, 3, gl.FLOAT, gl.FALSE, fsize 8, fsize 3);
gl.enableVertexAttribArray(aNormal);
复制代码
由顶点着色器传给片段着色器中

// 顶点着色器
attribute vec3 aNormal;
varying vec3 Normal;
void main () {

Normal = aNormal;
...

}

// 片段着色器
varying vec3 Normal;
void main () {

// 进行归一化
vec3 norm = normalize(Normal);

}
复制代码
由像素位置与光源方向计算出入射向量,像素的位置就是顶点也是已知的,光源位置是统一的用uniform变量存储

// 顶点着色器
attribute vec3 aPos;
varying vec3 FragPos;
void main () {

FragPos = aPos;
...

}

// 片段着色器
varying vec3 FragPos;
uniform vec3 lightPos;
void main () {

vec3 lightDir = normalize(lightPos - FragPos);

}
复制代码
最后根据公式算出漫反射分量

// 片段着色器
void main () {

float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * color;

}
复制代码
镜面反射
当我们观察有光泽的对象时就会看到高光。这些高光通常表现出与环境光反射和漫反射不同的颜色。而且与漫反射表面是粗糙的相反,镜面反射表面是光滑的。表面越光滑,就越接近于镜面,反射出去的光线就越集中在一个角度的附近。
image.png
Phong提出了一个近似的模型,在考虑镜面反射时,把表面看成是光滑的。观察者所看到的光线强度取决于反射光线的方向r和观察者的方向v这两者之间的夹角α。

Ls=ksLscospαL_s = k_sL_scos^pαLs​=ks​Ls​cospα

其中系数ksk_sks​(0 <= ksk_sks​ <= 1)表示在入射的镜面反射光中的有多大一部分被反射。指数p是高光系数。从下图可以看出,当p增加时,反射的光线越来越集中在理想反射器的反射角附近。

当不加p时(即p=1),我们从反射角度是60度的时候看着色点,按理说是离的很偏的了,但反映出来还是能看见高光。这就不合理了,因为在现实中只有非常接近的时候才能看见高光,稍微离远一点就看不到。所以才加上一个指数让其正常化。

Phone反射模型优点在于,如果已经把r和v归一化为单位向量,那么可以像计算漫反射一样利用点积运算计算镜面反射分量:

Ls=ksLsmax((r∗v)p,0)L_s = k_sL_smax((r * v)^p, 0)Ls​=ks​Ls​max((r∗v)p,0)

接下来只需计算出反射向量r即可!

反射角计算
法向量是给出的,利用法向量n和入射向量l就可以算出反射角。理想的镜面反射有一个很好的特征:入射角等于反射角。如图所示:
image.png
入射角是法向量和入射向量的夹角,反射角是法向量和反射光线之间的夹角。在平面内,只有一个反射方向能满足入射角等于反射角这个条件。但在三维空间中就不行,因为有无数个方向都满足入射角等于反射角。所以要加上一个条件:在表面上的一点p,入射光线和反射光线必须位于同一个平面内。这两个条件可以由n和l确定r。

假设l和n已经是单位向量:

|l| = |n| = 1。

同时也假定r也是单位向量:

|r| = 1

如果θIθ_IθI​=θrθ_rθr​那么

cosθicosθ_icosθi​ = cosθrcosθ_rcosθr​

利用点积运算可得:

cosθicosθ_icosθi​ = l n = cosθrcosθ_rcosθr​ = n r

共面的条件意味着可以把r写成l和n的线性组合:

r = αl + βn(1)

等号两边都和n做点积可得等式(2):

n r = αl n + β = l * n(2)

因为r是单位向量,所以代入等式(1)可得等式(3):

1 = r r = α2α^2α2 + 2αβl n + β2β^2β2(3)

结合等式(2)和等式(3)可得

r = 2(l * n))n - l

代码实现
上述计算反射角的公式,在glsl中有一个内置函数reflect实现了。所以在代码中实现非常简单,视线向量也是已知的。

// 片段着色器
uniform vec3 viewPos;
void main () {

vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
vec3 specular = vec3(0.3) * pow(max(dot(viewDir, reflectDir), 0.0), 8.0);

}
复制代码
Phong反射模型结果
将上述3种分量加在一起就是Phong反射模型

L=La+Ld+LsL = L_a + L_d + L_sL=La​+Ld​+Ls​
=kaIa+kd(I/r2)max(0,n∗l)+ksLsmax((r∗v)p,0)= k_aI_a + k_d(I/r^2)max(0, nl) + k_sL_smax((r v)^p, 0)=ka​Ia​+kd​(I/r2)max(0,n∗l)+ks​Ls​max((r∗v)p,0)

gl_FragColor = vec4(ambient + diffuse + specular, 1.0);
复制代码
效果图如下

image.png

Phong反射模型不仅对真实光照有很好的近似,而且性能也很高。但它的镜面反射会在一些情况下出现问题,特别是物体反光度很低时,会导致大片高光区域。

出现这个问题的原因是观察向量和反射向量间的夹角不能大于90度。如果点积结果为负数,镜面反射会变为0。你可能会觉得,当光线与视线的夹角大于90度时,应该不会接收到任何光才对。这种想法仅仅适合于漫反射。

但在镜面反射中,测量的角度并不是光源与法线的夹角,而是视线与反射光线向量的夹角,如下图。
image.png
右图中,视线与反射方向之间的夹角明显大于90度,这种情况下镜面光分量为0。这在大多数情况下是没问题的,因为观察方向离反射方向都非常远。然而,当物体的反光度非常小时,它产生的镜面高光半径足以让这些相反反向的光线对亮度产生足够大的影响,在这种情况下就不能忽略它们对镜面光分量的贡献了。

而且反射角也比较难算。

所以在Phong的基础上,Blinn对此加以拓展,引入了Blinn-Phong反射模型。

Blinn-Phong反射模型
该模型与Phong模型的区别只有在镜面光分量处理上有一些差别。Blinn-Phong反射模型不再依赖反射角,而是采用半程向量,即光线与视线夹角一半的方向上的单位向量。

半程向量
当观察方向接近镜面反射方向时,物体表面法线方向与半程向量接近。

image.png

所谓的半程向量就是光照方向向量与观察方向向量根据平行四边形法则加起来再除以它的长度就能得到。

h=(v+l)/∣v+l∣h = (v + l) / |v + l|h=(v+l)/∣v+l∣

h与n接近就说明了v和r接近,这就是Blinn-Phong模型的特别之处。因为r和v的夹角比较难计算的,用了这个小技巧后,计算便简单很多。

与漫反射原理几乎差不多,只不过是将光照方向与法线方向的夹角换成了半程向量与法线方向的夹角而已

Ls=ks(I/r2)max(0,n∗h)pL_s = k_s(I / r^2)max(0, n * h)^pLs​=ks​(I/r2)max(0,n∗h)p

代码实现
vec3 halfwayDir = normalize(lightDir + viewDir);
vec3 specular = vec3(0.3) * pow(max(dot(norm, halfwayDir), 0.0), 32.0);
复制代码
效果图如下

image.png

最后
如果你觉得此文对你有一丁点帮助,点个赞。或者可以加入我的开发交流群:1025263163相互学习,我们会有专业的技术答疑解惑

如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star:http://github.crmeb.net/u/defu不胜感激 !

PHP学习手册:https://doc.crmeb.com
技术交流论坛:https://q.crmeb.com

今天关于[computer graphics] 简单光照模型 (Phong 和 Blinn-Phong) 和明暗处理phong光照明模型公式的分享就到这里,希望大家有所收获,若想了解更多关于6GEN715 – Computer Graphics、A Self-Organized Computer Virus Demo in C、Blinn-phong model importance sampling、Blinn-Phong反射模型等相关知识,可以在本站进行查询。

本文标签: