- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在用 java 开发一个简单的渲染引擎,它可以将 OBJ 文件渲染到屏幕上。我目前正在研究照明系统,该系统用于照亮屏幕上出现的模型。在介绍照明系统之前,我能够轻松地将模型加载到屏幕上:
但是,当我向屏幕添加灯光时,模型不再显示。我使用以下着色器来渲染灯光:
顶点着色器:
#version 150
in vec3 position;
in vec2 textureCoordinates;
in vec3 normals;
out vec2 passTextureCoordinates;
out vec3 surfaceNormal;
out vec3 toLightVector;
uniform mat4 transformationMatrixTextured;
uniform mat4 projectionMatrixTextured;
uniform mat4 viewMatrixTextured;
uniform vec3 lightLocation;
void main(void){
vec4 worldPosition = transformationMatrixTextured * vec4(position,1.0);
gl_Position = projectionMatrixTextured * viewMatrixTextured * worldPosition;
passTextureCoordinates = textureCoordinates;
surfaceNormal = (transformationMatrixTextured * vec4(normals,0.0)).xyz;
toLightVector = lightLocation - worldPosition.xyz;
}
片段着色器:
#version 150
in vec2 passTextureCoordinates;
in vec3 surfaceNormal;
in vec3 toLightVector;
out vec4 out_Color;
uniform sampler2D textureSampler;
uniform vec3 lightColor;
void main(void){
vec3 unitNormal = normalize(surfaceNormal);
vec3 unitLightVector = normalize(toLightVector);
float nDot1 = dot(unitNormal, unitLightVector);
float brightness = max(nDot1, 0.0);
vec3 diffuse = brightness * lightColor;
out_Color = vec4(diffuse, 1.0) * texture(textureSampler,passTextureCoordinates);
}
我一直在使用tutorial series by ThinMatrix帮助我创建这个程序。然而,一个很大的区别是我还希望能够加载以编程方式创建的模型,而不是仅使用 OBJLoader 加载的模型。因此,我必须创建一种方法来计算给定顶点数组和索引数组的法线。
我解决这个问题的方法是这样的:
/**
* Sum.
*
* @param arg1 the arg 1
* @param arg2 the arg 2
* @return the vector 3 f
*/
public static Vector3f sum(Vector3f arg1, Vector3f arg2) {
return new Vector3f(arg1.x + arg2.x, arg1.y + arg2.y, arg1.z + arg2.z);
}
/**
* Subtract.
*
* @param arg1 the arg 1
* @param arg2 the arg 2
* @return the vector 3 f
*/
public static Vector3f subtract(Vector3f arg1, Vector3f arg2) {
return new Vector3f(arg1.x - arg2.x, arg1.y - arg2.y, arg1.z - arg2.z);
}
/**
* Cross product.
*
* @param arg1 the arg 1
* @param arg2 the arg 2
* @return the vector 3 f
*/
public static Vector3f crossProduct(Vector3f arg1, Vector3f arg2) {
return new Vector3f(arg1.y * arg2.z - arg2.y * arg1.z, arg2.x * arg1.z - arg1.x * arg2.z, arg1.x * arg2.y - arg2.x * arg1.y);
}
/**
* Gets the normals.
*
* @param vertices the vertices
* @param indexes the indexes
* @return the normals
*/
public static float[] getNormals(float[] vertices, int[] indexes) {
vertices = convertToIndexless(vertices, indexes);
Vector3f tmp;
float[] tmpArray = new float[vertices.length / 3];
int tmpArrayCounter = 0;
for(int i = 0; i < vertices.length; i+=9) {
Vector3f edge1 = subtract(new Vector3f(vertices[i], vertices[i + 1], vertices[i + 2]) , new Vector3f(vertices[i + 3], vertices[i + 4], vertices[i + 5]));
Vector3f edge2 = subtract(new Vector3f(vertices[i], vertices[i + 1], vertices[i + 2]) , new Vector3f(vertices[i + 6], vertices[i + 7], vertices[i + 8]));
tmp = crossProduct(edge1, edge2);
tmpArray[tmpArrayCounter++] = tmp.getX();
tmpArray[tmpArrayCounter++] = tmp.getY();
tmpArray[tmpArrayCounter++] = tmp.getZ();
}
return tmpArray;
}
/**
* Convert to indexless.
*
* @param vertices the vertices
* @param indexes the indexes
* @return the float[]
*/
private static float[] convertToIndexless(float[] vertices, int[] indexes) {
float[] tmpArray = new float[indexes.length * 3];
for(int i = 0; i < indexes.length; i++) {
tmpArray[i * 3] = vertices[indexes[i] * 3];
tmpArray[i * 3 + 1] = vertices[indexes[i] * 3 + 1];
tmpArray[i * 3 + 2] = vertices[indexes[i] * 3 + 2];
}
return tmpArray;
}
我的这种方法基于 this question关于计算法线。正如我之前所说,在向程序添加灯光时我无法渲染模型。我的计算有问题吗?
最佳答案
长描述以找出根本问题
老实说我不明白什么意思the model does no longer show up
。因此,我将发布一些提示,让您了解如何了解正在发生的情况。
渲染的模型是全黑的吗?
可能有多个问题来源需要检查:
face culling
找出答案。如果它使用背面渲染进行渲染,那么模型的法线就是一个问题intensity = max(dot(n, l), ambience);
在顶点着色器中使用 ambience
作为参数和 n
物体的归一化法线和 l
标准化的光方向。在片段着色器中我使用 gl_FragColor = vec4(intensity*tc.r,intensity*tc.g,intensity*tc.b,tc.a);
与 tc
是 vec4 纹理坐标。这样物体总是有一些光着色器代码是否有错误?编译错误被记录为异常?
我猜问题是使用叉积和错误的光线方向的混合(我一开始在我的模型中也遇到了同样的问题)
编辑对点积的另一条评论:点积是找出强度所需的。它的几何定义dot(a,b)=length(a)*length(b)*cos(alpha)
哪里alpha
是 a 和 b 之间的角度。
如果模型法线与光线方向相同,那么您需要完整的强度。
如果模型法线与光线方向正交(90 度),那么您需要 0 强度(或环境强度)
如果模型法线与光线方向成 60 度,那么您需要一半强度(或环境强度)
等等
编辑2 - 因为点积现在可能会产生负结果 max(dot(a,b),0)
会将其剪掉(用于相反方向)。为了快速营造氛围,您可以将其更改为 max(dot(a,b),0.3)
摘要:
使用点积计算强度。
使用环境光来保留一些光线,即使相对于光源的角度不好。
关于java - 计算模型照明的法线会导致模型不再渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53187887/
所以昨天我写了 WaveFront .obj 3D 模型加载器,它现在工作正常(虽然不支持所有内容)所以我写了简单的测试来在屏幕上绘制任何 3D 模型,在我为场景添加照明之前一切正常.光出现了,但法线
我的代码(用 C++ 编码)在处理更新模型法线的 for 循环中存在瓶颈。我用来测试的模型有大约 ~2.2k 个顶点(指示),工作正常并且在 60 fps 限制下工作,但法线与指示器(~12k)一样多
我无法将法线和 u,v 对发送到我的着色器。如果我删除法线,一切都会按预期进行。 编辑看起来 v_normal 正在接收用于 v_coord 的值。我仍然不知道。/编辑 这是我的顶点: struct
我正在寻找一种方法来获取矩形的所有顶点,该矩形的中心、法线、长度和高度我都知道。我的数学有点弱所以请帮助我。编辑:飞机在 3D 空间中。 最佳答案 通过从中心点的 x/y 位置减去/加上宽度/高度的一
是否可以从片段着色器内访问表面法线(与片段平面相关的法线)?或者也许这可以在顶点着色器中完成? 当我们沿着着色器管道走下去时,相关几何体的所有知识是否都会丢失,或者是否有一些巧妙的方法可以在片段着色器
我无法使用 VBO 正确渲染法线。下面是我正在使用的代码,顶点是一个包含顶点的数组,法线是一个包含法线的数组: //Create the buffers and such GLuint VBOID;
我已经有了这个不再那么小的基于图 block 的游戏,这是我的第一个真正的 OpenGL 项目。我想将每个图 block 渲染为 3D 对象。因此,首先我创建了一些对象,例如立方体和球体,为它们提供了
我正在尝试添加一个垂直于我单击的面的框(称为“标记”)。 为此,单击时,我会转换一条射线,如果它击中某些物体,我会获取法线的交点值并将它们传输到“标记”作为其旋转值。在问这个问题之前,我阅读了这个答案
这与另一个问题(那里的图像)中描述的问题有关: Opengl shader problems - weird light reflection artifacts 我有一个 .obj 导入器,它创建一
我正在尝试制作一个在 OpenGL 2.1 和 Qt5 中渲染的简单 map 。但我在非常基本的问题上失败了。我在这里展示的是表面法线。 我有 4 个由单个三角形几何体组成的对象。一个简单的几何图形是
我正在开发一个类似 JavaScript/Canvas 3D FPS 的引擎,迫切需要一个法线向量(如果您愿意,也可以是观察向量)来进行近平面和远平面裁剪。我有 x 轴和 y 轴旋转 Angular
我正在编写用于在我的 DirectX 应用程序中存储、加载和渲染静态网格的类。 我知道 Box 模型可以使用 8 个顶点,但通常它使用 24 或 36 个(因为一个“空间中的顶点”实际上是 3 个具有
我无法使 phong 着色看起来正确。我很确定我的 OpenGL 调用或我加载法线的方式有问题,但我想这可能是其他问题,因为 3D 图形和 Assimp 对我来说都还很陌生。尝试加载 .obj/.mt
我是一名优秀的程序员,十分优秀!