gpt4 book ai didi

java - 计算模型照明的法线会导致模型不再渲染

转载 作者:行者123 更新时间:2023-11-30 05:55:59 28 4
gpt4 key购买 nike

我正在用 java 开发一个简单的渲染引擎,它可以将 OBJ 文件渲染到屏幕上。我目前正在研究照明系统,该系统用于照亮屏幕上出现的模型。在介绍照明系统之前,我能够轻松地将模型加载到屏幕上:

enter image description here

但是,当我向屏幕添加灯光时,模型不再显示。我使用以下着色器来渲染灯光:

顶点着色器:

#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 纹理坐标。这样物体总是有一些光
          • 或者着色器代码中的一些错误(乍一看无法发现问题,但谁知道呢?)好吧,我为此使用了模型法向光方向的点积,在您的代码中似乎有十字产品。
      • 纹理未使用/接受/分配给模型,或者 vector 仅返回一个全黑的像素位置
    • 着色器代码是否有错误?编译错误被记录为异常?

      • 修复它;)

我猜问题是使用叉积和错误的光线方向的混合(我一开始在我的模型中也遇到了同样的问题)

编辑对点积的另一条评论:点积是找出强度所需的。它的几何定义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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com