您当前的位置: 首页 >  ar

Jave.Lin

暂无认证

  • 4浏览

    0关注

    704博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

LearnGL - 15.1 - Reflection - 反射效果

Jave.Lin 发布时间:2020-08-07 14:14:19 ,浏览量:4

文章目录
  • 先看看效果
  • 思路
  • 构造 cube map、纯颜色环境光
  • 计算反射向量
  • 添加对环境反射的强度 ReflectionK
    • 完整的 my_global.glsl
    • 完整的 my_lighting.glsl
  • References

LearnGL - 学习笔记目录

前一篇:LearnGL - 15 - Skybox - 天空盒 - 了解了如何构造一个天空盒

这一篇:实现类似环境反射的效果,我们可以使用纯颜色、天空盒来做反射采样的颜色。

总体来说我现实的这种比较简单,不过很多都是基于之前的内容类实现的。

本人才疏学浅,如有什么错误,望不吝指出。

先看看效果

在这里插入图片描述 在这里插入图片描述

在这里插入图片描述

思路
  • 构造好用于环境反射用的 cube map,或是纯颜色的 环境颜色,并传入到 shader
  • 计算反射向量,用于采样 cube_map,或是纯颜色
  • 添加对环境反射的强度 ReflectionK
构造 cube map、纯颜色环境光
  • 构造 cube map:可参考前一篇:LearnGL - 15 - Skybox - 天空盒
  • 纯颜色环境光,也可以参考之前我们的: LearnGL - 11.1 - 实现简单的Gouraud光照模型 本身就有了,可以直接拿来用即可
计算反射向量

用到 r e f l e c t ( I , N ) reflect(I, N) reflect(I,N),也可以参考会之前的 LearnGL - 11.1 - 实现简单的Gouraud光照模型 - reflect - 反射高光方向

在这里插入图片描述

添加对环境反射的强度 ReflectionK

这个具体看 shader 了

在这里插入图片描述 在这里插入图片描述

主要看:calculateReflection 函数

void calculateReflection(vec3 worldNormal, vec3 viewDir, inout vec3 albedo) {
		if (Material.ReflectionK > 0) {
		vec3 reflection_color   = albedo;
		if (ClearType == CLEAR_TYPE_SKYBOX) {											// 天空盒的
			vec3 R = reflect(-viewDir, worldNormal);
			reflection_color 	= texture(SkyboxTex, R).rgb;
		} else if (ClearType == CLEAR_TYPE_COLOR) {										// 清理颜色的
			reflection_color 	= ClearColor;											// 不用计算反射
		}
		albedo             		= mix(albedo, reflection_color, Material.ReflectionK);
	}
}
完整的 my_global.glsl
// jave.lin - my_global.glsl

#ifndef _MY_GLOBAL__GLSL__
#define _MY_GLOBAL__GLSL__

#define CLEAR_TYPE_COLOR 0
#define CLEAR_TYPE_SKYBOX 1

// camera uniform
uniform vec3 _CamWorldPos;		// 镜头世界坐标

uniform int ClearType;			// 渲染相机的 clear type
uniform vec3 ClearColor;		// 清理的颜色
uniform samplerCube SkyboxTex; 	// 天空盒

// scene uniform
uniform vec4 _Ambient;		// .xyz 环境光颜色, .w 环境光系数
uniform int AmbientType;	// 环境光类别,[测试用]

// local uniform
uniform mat4 mMat; 				// m 矩阵
uniform mat4 vMat; 				// v 矩阵
uniform mat4 pMat; 				// p 矩阵
uniform mat4 mvpMat; 			// m.v.p 矩阵
uniform mat4 IT_mMat;			// Model Matrix 的逆矩阵的转置矩阵

// 将对象空间的法线转换到世界空间下的法线
vec3 ObjectToWorldNormal(vec3 n) {
	return normalize(mat3(IT_mMat) * n);	// 等价于:transpose(I_mMat) * vec4(n, 0)
}

vec3 getWorldViewDir(vec3 worldPos) {
	return normalize(_CamWorldPos - worldPos);
}

#endif /* _MY_GLOBAL__GLSL__ */ // 这里一定要加 /* 你的头文件宏 */,否则会报错,太无语了
完整的 my_lighting.glsl
// jave.lin - my_lighting.glsl - 光照模型处理

#include "/Include/my_global.glsl"

#ifndef _MY_LIGHTING__GLSL__
#define _MY_LIGHTING__GLSL__

#define DIRECTIONAL_LIGHT_TYPE 0
#define POINT_LIGHT_TYPE 1
#define SPOT_LIGHT_TYPE 2

// 材质属性 - 很多的属性可以合并到其他没有满4个分量的属性,但学习目的,为了可读性高,可以分开来
struct Material_t {
	float Glossy;			// 光滑度
	vec3 Emission;			// 自发光颜色
	vec3 DiffuseK;			// 漫反射系数
	vec3 SpecularK;			// 高光系数
	float ReflectionK;		// 反射系数
};
uniform Material_t Material;

// 灯光属性 - 很多的属性可以合并到其他没有满4个分量的属性,但学习目的,为了可读性高,可以分开来
// 灯光属性也可以按类型来分为不同的材质结构体
// 但是为了编写方便,就没有分开了
struct LightData_t {
	// common properties
	int 	Enabled;		// 是否开启
	int 	Type;			// 灯光类似
	vec3 	Color;			// 灯光颜色
	float 	Intensity;		// 强度
	// directional or spot light
	vec3 	Direction;		// 方向光 或 聚光灯 照射方向
	// point or spot light
	vec3 	Position;		// 点光源 或 聚光灯 灯光世界坐标位置
	float 	ATTEN_Kc;		// 点光源 常数项系数
	float 	ATTEN_Kl;		// 点光源 一次项系数
	float 	ATTEN_Kq;		// 点光源 二次项系数
	vec2 	ATTEN_Range;	// 点光源 有效范围, .x == range, .y == 1.0 / range
	// spot light
	float 	SpotFOL; 		// 聚光灯的张角量,Field Of Light(弧度)
	float 	SpotFOL_FadeOut;// 这个边缘淡出的角度,必须小于 SpotFOL,否则没有效果
};
const uint MaxLightNum = 10;
uniform LightData_t Lights[MaxLightNum];

// ambient
vec3 getAmbient(vec3 albedo) {
	if (AmbientType == 0) 	return _Ambient.rgb * _Ambient.a;
	else 					return mix(_Ambient.rgb * _Ambient.a, albedo, _Ambient.a);
}

// point or spot light 的光距离衰减
float getDistanceAtten(float dist, LightData_t light) {		// 获取距离衰减
	// 由原来的 atten = 1 / (kc + kl * dist + kq * dist * dist) 改为只用一个 sommthstep就够了
	// smoothstep 的曲线取反,即:1 - smoothstep,结果的曲线也不错
	return 1 - smoothstep(0, light.ATTEN_Range.x, dist);
}

void phong_illumination(
    in vec3 worldNormal,
    in vec3 viewDir,
    in vec3 worldPos,
    out vec3 diffuse,
    out vec3 specular
    ) {
	for	(int i = 0; i  0) S = pow(max(0, dot(H, worldNormal)), Material.Glossy);
		specular += light.Color * light.Intensity * S * Material.SpecularK * atten;
	}
}

void calculateReflection(vec3 worldNormal, vec3 viewDir, inout vec3 albedo) {
		if (Material.ReflectionK > 0) {
		vec3 reflection_color   = albedo;
		if (ClearType == CLEAR_TYPE_SKYBOX) {											// 天空盒的
			vec3 R = reflect(-viewDir, worldNormal);
			reflection_color 	= texture(SkyboxTex, R).rgb;
		} else if (ClearType == CLEAR_TYPE_COLOR) {										// 清理颜色的
			reflection_color 	= ClearColor;											// 不用计算反射
		}
		albedo             		= mix(albedo, reflection_color, Material.ReflectionK);
	}
}

#endif
References
  • 立方体贴图
关注
打赏
1664331872
查看更多评论
立即登录/注册

微信扫码登录

0.0813s