- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试在片段着色器中实现 Oren-Nayar 光照,如图所示 here .
但是,我在地形上得到了一些奇怪的光照效果,如下所示。
我目前正在向着色器发送“视角方向”制服作为相机的“前” vector 。我不确定这是否正确,因为四处移动相机会改变伪像。
将“前” vector 乘以 MVP 矩阵可获得更好的结果,但从某些角度查看地形时,伪像仍然非常明显。在黑暗区域和屏幕边缘周围尤其明显。
是什么导致了这种影响?
工件示例
场景应该是什么样子
顶点着色器
#version 450
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
out VS_OUT {
vec3 normal;
} vert_out;
void main() {
vert_out.normal = normal;
gl_Position = vec4(position, 1.0);
}
segmentation 控制着色器
#version 450
layout(vertices = 3) out;
in VS_OUT {
vec3 normal;
} tesc_in[];
out TESC_OUT {
vec3 normal;
} tesc_out[];
void main() {
if(gl_InvocationID == 0) {
gl_TessLevelInner[0] = 1.0;
gl_TessLevelInner[1] = 1.0;
gl_TessLevelOuter[0] = 1.0;
gl_TessLevelOuter[1] = 1.0;
gl_TessLevelOuter[2] = 1.0;
gl_TessLevelOuter[3] = 1.0;
}
tesc_out[gl_InvocationID].normal = tesc_in[gl_InvocationID].normal;
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
segmentation 评估着色器
#version 450
layout(triangles, equal_spacing) in;
in TESC_OUT {
vec3 normal;
} tesc_in[];
out TESE_OUT {
vec3 normal;
float height;
vec4 shadow_position;
} tesc_out;
uniform mat4 model_view;
uniform mat4 model_view_perspective;
uniform mat3 normal_matrix;
uniform mat4 depth_matrix;
vec3 lerp(vec3 v0, vec3 v1, vec3 v2) {
return (
(vec3(gl_TessCoord.x) * v0) +
(vec3(gl_TessCoord.y) * v1) +
(vec3(gl_TessCoord.z) * v2)
);
}
vec4 lerp(vec4 v0, vec4 v1, vec4 v2) {
return (
(vec4(gl_TessCoord.x) * v0) +
(vec4(gl_TessCoord.y) * v1) +
(vec4(gl_TessCoord.z) * v2)
);
}
void main() {
gl_Position = lerp(
gl_in[0].gl_Position,
gl_in[1].gl_Position,
gl_in[2].gl_Position
);
tesc_out.normal = normal_matrix * lerp(
tesc_in[0].normal,
tesc_in[1].normal,
tesc_in[2].normal
);
tesc_out.height = gl_Position.y;
tesc_out.shadow_position = depth_matrix * gl_Position;
gl_Position = model_view_perspective * gl_Position;
}
片段着色器
#version 450
in TESE_OUT {
vec3 normal;
float height;
vec4 shadow_position;
} frag_in;
out vec4 colour;
uniform vec3 view_direction;
uniform vec3 light_position;
#define PI 3.141592653589793
void main() {
const vec3 ambient = vec3(0.1, 0.1, 0.1);
const float roughness = 0.8;
const vec4 water = vec4(0.0, 0.0, 0.8, 1.0);
const vec4 sand = vec4(0.93, 0.87, 0.51, 1.0);
const vec4 grass = vec4(0.0, 0.8, 0.0, 1.0);
const vec4 ground = vec4(0.49, 0.27, 0.08, 1.0);
const vec4 snow = vec4(0.9, 0.9, 0.9, 1.0);
if(frag_in.height == 0.0) {
colour = water;
} else if(frag_in.height < 0.2) {
colour = sand;
} else if(frag_in.height < 0.575) {
colour = grass;
} else if(frag_in.height < 0.8) {
colour = ground;
} else {
colour = snow;
}
vec3 normal = normalize(frag_in.normal);
vec3 view_dir = normalize(view_direction);
vec3 light_dir = normalize(light_position);
float NdotL = dot(normal, light_dir);
float NdotV = dot(normal, view_dir);
float angleVN = acos(NdotV);
float angleLN = acos(NdotL);
float alpha = max(angleVN, angleLN);
float beta = min(angleVN, angleLN);
float gamma = dot(view_dir - normal * dot(view_dir, normal), light_dir - normal * dot(light_dir, normal));
float roughnessSquared = roughness * roughness;
float roughnessSquared9 = (roughnessSquared / (roughnessSquared + 0.09));
// calculate C1, C2 and C3
float C1 = 1.0 - 0.5 * (roughnessSquared / (roughnessSquared + 0.33));
float C2 = 0.45 * roughnessSquared9;
if(gamma >= 0.0) {
C2 *= sin(alpha);
} else {
C2 *= (sin(alpha) - pow((2.0 * beta) / PI, 3.0));
}
float powValue = (4.0 * alpha * beta) / (PI * PI);
float C3 = 0.125 * roughnessSquared9 * powValue * powValue;
// now calculate both main parts of the formula
float A = gamma * C2 * tan(beta);
float B = (1.0 - abs(gamma)) * C3 * tan((alpha + beta) / 2.0);
// put it all together
float L1 = max(0.0, NdotL) * (C1 + A + B);
// also calculate interreflection
float twoBetaPi = 2.0 * beta / PI;
float L2 = 0.17 * max(0.0, NdotL) * (roughnessSquared / (roughnessSquared + 0.13)) * (1.0 - gamma * twoBetaPi * twoBetaPi);
colour = vec4(colour.xyz * (L1 + L2), 1.0);
}
最佳答案
首先,我将您的片段着色器与我的 View /法线/光 vector 一起插入到我的渲染器中,并且效果很好。所以问题一定出在你计算这些 vector 的方式上。
接下来,您说您将 view_dir
设置为相机的前 vector 。我假设您的意思是“世界空间中相机的前 vector ”,这是不正确的。由于您在相机空间中使用 vector 计算点积,因此 view_dir
也必须在相机空间中。那就是 vec3(0,0,1)
将是一种简单的检查方法。如果有效——我们发现了您的问题。
但是,在进行透视投影时,使用 (0,0,1)
作为 View 方向并不严格正确,因为从片段到相机的方向取决于片段的位置画面上的片段。正确的公式是 view_dir = normalize(-pos)
,其中 pos
是片段在相机空间中的位置(即在没有投影的情况下应用模型 View 矩阵)。此外,此数量现在仅取决于屏幕上的片段位置,因此您可以将其计算为:
view_dir = normalize(vec3(-(gl_FragCoord.xy - frame_size/2) / (frame_width/2), flen))
flen
是您相机的焦距,您可以计算为 flen = cot(fovx/2)
。
关于c++ - OpenGL 中的 Oren-Nayar 光照(如何在片段着色器中计算 View 方向),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40583715/
我正在使用 JOGL 库开发一些 OpenGL 游戏。 当我定期绘制物体时,例如直接在显示方法中使用GL_QUADS,场景照明出现在对象上。 但是,当我在 init 方法中准备对象并在显示列表中使用
我正在写一个非常小的游戏,在这个游戏中玩家拿着手电筒。 游戏发生的世界是一个小房子。 问题是我的墙是通过绘制多边形绘制的,一个多边形就是一面墙。因此,当我将光照射到墙上时,它不会亮起,只有当光照射到其
我只是在编写一个简单的程序来使用顶点数组对象绘制体素。当我运行程序时,我无法使照明正常工作,它看起来与未启用灯时一样。这是代码片段。显示功能 void GraphicVoxel::display()
我和我的团队刚刚将我们的游戏从 java2d 移植到 LWJGL,现在想要添加照明。我们到底想添加什么: 发光且可移动的元素/实体。 静态照明 我们已经用谷歌搜索了一段时间,但有点迷失,因为我们不知道
所以我有一个 3D 对象,我用以下光线绘制: GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 0.9}; /* White light. */ GLflo
我试图找到加载到 opengl 程序中的任意对象的 vector 归一化。我正在尝试计算所有顶点的法线。我收集到的是,我需要首先计算面的法线,然后找到顶点法线的平均值。 当我运行程序时,某些对象被正确
我正在尝试在 Vulkan 着色器中为单个光源实现 Blinn-Phong 着色,但我得到的结果不是我所期望的。 输出如下所示: 灯光位置应在相机右侧的后面,这在图里上正确表示,但在圆圈上却没有。我不
我已经有了这个不再那么小的基于图 block 的游戏,这是我的第一个真正的 OpenGL 项目。我想将每个图 block 渲染为 3D 对象。因此,首先我创建了一些对象,例如立方体和球体,为它们提供了
这是我第一次尝试创建一个基本的灯光系统,该系统使用顶部有白色圆圈的黑色纹理。我阅读了有关该问题的各种帖子,但我只是不知道我做错了什么。 我想要的是环境是黑暗的,光线是白色的,但是将 spritebat
我是 GLES 2.0 的新手。这真的让我很紧张,因为 OpenGL ES 1 II 只是设置了 GL_LIGHTNING1,然后设置了光照。在 GLES 2.0 中它不起作用。实际上整个屏幕都是黑色
我想问一个关于我在 OpenGL 中的光照效果的问题。 我正在尝试添加照明,但我认为这不是很好,而且我看到一些 2D 照明图片比我的好得多。 问题:我做了一个聚光灯,但我希望它能随着光照范围变小而变暗
我又回到了 Unity。我曾经使用 Unity 4 来创建我的关卡,在那里我可以从我的枪中射出实时灯光。我也使用 Probuilder 来创建我的场景,并且有很多汽车和巡逻 guard 。而且很顺利。
图像素描特效 图像素描特效主要经过以下几个步骤: 调用cv.cvtcolor()函数将彩色图像灰度化处理; 通过cv.gaussianblur()函数实现高斯滤波降噪; 边缘检测采用canny算
我正在尝试在片段着色器中实现 Oren-Nayar 光照,如图所示 here . 但是,我在地形上得到了一些奇怪的光照效果,如下所示。 我目前正在向着色器发送“视角方向”制服作为相机的“前” vect
我有一张包含很多 Sprite 的 map 。我可以向具有漫反射阴影的 Sprite 添加 Material ,而不是添加大量灯光。但这不会给我想要的结果。并且性能很重。 例子 在第一张图片中,您可以
我是一名优秀的程序员,十分优秀!